Compare commits
1 commit
main
...
feat/chann
Author | SHA1 | Date | |
---|---|---|---|
a2f9e87154 |
28 changed files with 44632 additions and 123 deletions
93
codegen/src/collect_datetimes.rs
Normal file
93
codegen/src/collect_datetimes.rs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
use std::{collections::BTreeMap, fs::File, io::BufReader, path::Path};
|
||||||
|
|
||||||
|
use futures::{stream, StreamExt};
|
||||||
|
use path_macro::path;
|
||||||
|
use rustypipe::{
|
||||||
|
client::RustyPipe,
|
||||||
|
param::{locale::LANGUAGES, Language},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
|
type CollectedDates = BTreeMap<Language, String>;
|
||||||
|
|
||||||
|
const FILENAME: &str = "datetime_samples.json";
|
||||||
|
|
||||||
|
// A channel with an upcoming video or livestream
|
||||||
|
const CHANNEL_ID: &str = "UCWxlUwW9BgGISaakjGM37aw";
|
||||||
|
const VIDEO_ID: &str = "p9FfS9l2NVA";
|
||||||
|
|
||||||
|
const YEAR: u64 = 2023;
|
||||||
|
const YEAR_SHORT: u64 = 23;
|
||||||
|
const MONTH: u64 = 4;
|
||||||
|
const DAY: u64 = 14;
|
||||||
|
const HOUR: u64 = 15;
|
||||||
|
const HOUR_12: u64 = 3;
|
||||||
|
const MINUTE: u64 = 0;
|
||||||
|
|
||||||
|
/// Collect upcoming video dates from the TV client in every supported language
|
||||||
|
/// and write them to `testfiles/dict/datetime_samples.json`
|
||||||
|
pub async fn collect_datetimes(project_root: &Path, concurrency: usize) {
|
||||||
|
let json_path = path!(project_root / "testfiles" / "dict" / FILENAME);
|
||||||
|
|
||||||
|
let rp = RustyPipe::new();
|
||||||
|
let collected_dates: CollectedDates = stream::iter(LANGUAGES)
|
||||||
|
.map(|lang| {
|
||||||
|
let rp = rp.clone();
|
||||||
|
println!("collecting {lang}");
|
||||||
|
async move {
|
||||||
|
let channel = rp.query().lang(lang).channel_tv(CHANNEL_ID).await.unwrap();
|
||||||
|
let video = channel
|
||||||
|
.videos
|
||||||
|
.into_iter()
|
||||||
|
.find(|v| v.id == VIDEO_ID)
|
||||||
|
.unwrap();
|
||||||
|
(
|
||||||
|
lang,
|
||||||
|
video
|
||||||
|
.publish_date_txt
|
||||||
|
.unwrap_or_else(|| panic!("no publish_date_txt in {}", lang)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.buffer_unordered(concurrency)
|
||||||
|
.collect()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let file = File::create(json_path).unwrap();
|
||||||
|
serde_json::to_writer_pretty(file, &collected_dates).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempt to parse the numbers collected by `collect-datetimes`
|
||||||
|
/// and write the results to `dictionary.json`.
|
||||||
|
pub fn write_samples_to_dict(project_root: &Path) {
|
||||||
|
let json_path = path!(project_root / "testfiles" / "dict" / FILENAME);
|
||||||
|
|
||||||
|
let json_file = File::open(json_path).unwrap();
|
||||||
|
let collected_dates: CollectedDates =
|
||||||
|
serde_json::from_reader(BufReader::new(json_file)).unwrap();
|
||||||
|
let mut dict = util::read_dict(project_root);
|
||||||
|
let langs = dict.keys().map(|k| k.to_owned()).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for lang in langs {
|
||||||
|
let datestr = &collected_dates[&lang];
|
||||||
|
let numbers = util::parse_numeric_vec::<u64>(datestr);
|
||||||
|
let order = numbers
|
||||||
|
.iter()
|
||||||
|
.map(|n| match *n {
|
||||||
|
YEAR => 'Y',
|
||||||
|
YEAR_SHORT => 'y',
|
||||||
|
MONTH => 'M',
|
||||||
|
DAY => 'D',
|
||||||
|
HOUR => 'H',
|
||||||
|
HOUR_12 => 'h',
|
||||||
|
MINUTE => 'm',
|
||||||
|
_ => panic!("unknown number {n} in {datestr} ({lang})"),
|
||||||
|
})
|
||||||
|
.collect::<String>();
|
||||||
|
assert_eq!(order.len(), 5);
|
||||||
|
dict.get_mut(&lang).unwrap().datetime_order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
util::write_dict(project_root, &dict);
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ pub async fn download_testfiles(project_root: &Path) {
|
||||||
channel_info(&testfiles).await;
|
channel_info(&testfiles).await;
|
||||||
channel_videos_cont(&testfiles).await;
|
channel_videos_cont(&testfiles).await;
|
||||||
channel_playlists_cont(&testfiles).await;
|
channel_playlists_cont(&testfiles).await;
|
||||||
|
channel_tv(&testfiles).await;
|
||||||
search(&testfiles).await;
|
search(&testfiles).await;
|
||||||
search_cont(&testfiles).await;
|
search_cont(&testfiles).await;
|
||||||
search_playlists(&testfiles).await;
|
search_playlists(&testfiles).await;
|
||||||
|
@ -412,6 +413,26 @@ async fn channel_playlists_cont(testfiles: &Path) {
|
||||||
playlists.content.next(rp.query()).await.unwrap().unwrap();
|
playlists.content.next(rp.query()).await.unwrap().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn channel_tv(testfiles: &Path) {
|
||||||
|
for (name, id) in [
|
||||||
|
("base", "UCXuqSBlHAE6Xw-yeJA0Tunw"),
|
||||||
|
("music", "UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
("live", "UCSJ4gkVC6NrvII8umztf0Ow"),
|
||||||
|
("live_upcoming", "UCWxlUwW9BgGISaakjGM37aw"),
|
||||||
|
("onevideo", "UCAkeE1thnToEXZTao-CZkHw"),
|
||||||
|
] {
|
||||||
|
let mut json_path = testfiles.to_path_buf();
|
||||||
|
json_path.push("channel_tv");
|
||||||
|
json_path.push(format!("{name}.json"));
|
||||||
|
if json_path.exists() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rp = rp_testfile(&json_path);
|
||||||
|
rp.query().channel_tv(id).await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn search(testfiles: &Path) {
|
async fn search(testfiles: &Path) {
|
||||||
let mut json_path = testfiles.to_path_buf();
|
let mut json_path = testfiles.to_path_buf();
|
||||||
json_path.push("search");
|
json_path.push("search");
|
||||||
|
|
|
@ -30,6 +30,19 @@ fn parse_tu(tu: &str) -> (u8, Option<TimeUnit>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_date_cmp(c: char) -> &'static str {
|
||||||
|
match c {
|
||||||
|
'Y' => "Y",
|
||||||
|
'y' => "YShort",
|
||||||
|
'M' => "M",
|
||||||
|
'D' => "D",
|
||||||
|
'H' => "Hr",
|
||||||
|
'h' => "Hr12",
|
||||||
|
'm' => "Mi",
|
||||||
|
_ => panic!("invalid date cmp: {c}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate_dictionary(project_root: &Path) {
|
pub fn generate_dictionary(project_root: &Path) {
|
||||||
let dict = util::read_dict(project_root);
|
let dict = util::read_dict(project_root);
|
||||||
|
|
||||||
|
@ -54,14 +67,20 @@ pub(crate) struct Entry {
|
||||||
/// Identifiers: `Y`(ear), `M`(month), `W`(eek), `D`(ay),
|
/// Identifiers: `Y`(ear), `M`(month), `W`(eek), `D`(ay),
|
||||||
/// `h`(our), `m`(inute), `s`(econd)
|
/// `h`(our), `m`(inute), `s`(econd)
|
||||||
pub timeago_tokens: phf::Map<&'static str, TaToken>,
|
pub timeago_tokens: phf::Map<&'static str, TaToken>,
|
||||||
/// Order in which to parse numeric date components. Formatted as
|
/// Order in which to parse numeric date components.
|
||||||
/// a string of date identifiers (Y, M, D).
|
|
||||||
///
|
///
|
||||||
/// Examples:
|
/// Examples:
|
||||||
///
|
///
|
||||||
/// - 03.01.2020 => `"DMY"`
|
/// - 03.01.2020 => `"DMY"`
|
||||||
/// - Jan 3, 2020 => `"DY"`
|
/// - Jan 3, 2020 => `"DY"`
|
||||||
pub date_order: &'static [DateCmp],
|
pub date_order: &'static [DateCmp],
|
||||||
|
/// Order in which to parse datetimes.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
///
|
||||||
|
/// - 2023-04-14 15:00 => `[Y,M,D,Hr,Mi]`
|
||||||
|
/// - 4/14/23, 3:00 PM => `[M,D,YShort,Hr12,Mi]`
|
||||||
|
pub datetime_order: &'static [DateCmp],
|
||||||
/// Tokens for parsing month names.
|
/// Tokens for parsing month names.
|
||||||
///
|
///
|
||||||
/// Format: Parsed token -> Month number (starting from 1)
|
/// Format: Parsed token -> Month number (starting from 1)
|
||||||
|
@ -131,10 +150,17 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
// Date order
|
// Date order
|
||||||
let mut date_order = "&[".to_owned();
|
let mut date_order = "&[".to_owned();
|
||||||
entry.date_order.chars().for_each(|c| {
|
entry.date_order.chars().for_each(|c| {
|
||||||
let _ = write!(date_order, "DateCmp::{c}, ");
|
let _ = write!(date_order, "DateCmp::{}, ", parse_date_cmp(c));
|
||||||
});
|
});
|
||||||
date_order = date_order.trim_end_matches([' ', ',']).to_owned() + "]";
|
date_order = date_order.trim_end_matches([' ', ',']).to_owned() + "]";
|
||||||
|
|
||||||
|
// Datetime order
|
||||||
|
let mut datetime_order = "&[".to_owned();
|
||||||
|
entry.datetime_order.chars().for_each(|c| {
|
||||||
|
let _ = write!(datetime_order, "DateCmp::{}, ", parse_date_cmp(c));
|
||||||
|
});
|
||||||
|
datetime_order = datetime_order.trim_end_matches([' ', ',']).to_owned() + "]";
|
||||||
|
|
||||||
// Number tokens
|
// Number tokens
|
||||||
let mut number_tokens = phf_codegen::Map::<&str>::new();
|
let mut number_tokens = phf_codegen::Map::<&str>::new();
|
||||||
entry.number_tokens.iter().for_each(|(txt, mag)| {
|
entry.number_tokens.iter().for_each(|(txt, mag)| {
|
||||||
|
@ -153,8 +179,8 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
let code_number_tokens = &number_tokens.build().to_string().replace('\n', "\n ");
|
let code_number_tokens = &number_tokens.build().to_string().replace('\n', "\n ");
|
||||||
let code_album_types = &album_types.build().to_string().replace('\n', "\n ");
|
let code_album_types = &album_types.build().to_string().replace('\n', "\n ");
|
||||||
|
|
||||||
let _ = write!(code_timeago_tokens, "{} => Entry {{\n by_char: {:?},\n timeago_tokens: {},\n date_order: {},\n months: {},\n timeago_nd_tokens: {},\n comma_decimal: {:?},\n number_tokens: {},\n album_types: {},\n }},\n ",
|
let _ = write!(code_timeago_tokens, "{} => Entry {{\n by_char: {:?},\n timeago_tokens: {},\n date_order: {},\n datetime_order: {},\n months: {},\n timeago_nd_tokens: {},\n comma_decimal: {:?},\n number_tokens: {},\n album_types: {},\n }},\n ",
|
||||||
selector, entry.by_char, code_ta_tokens, date_order, code_months, code_ta_nd_tokens, entry.comma_decimal, code_number_tokens, code_album_types);
|
selector, entry.by_char, code_ta_tokens, date_order, datetime_order, code_months, code_ta_nd_tokens, entry.comma_decimal, code_number_tokens, code_album_types);
|
||||||
});
|
});
|
||||||
|
|
||||||
code_timeago_tokens = code_timeago_tokens.trim_end().to_owned() + "\n }\n}\n";
|
code_timeago_tokens = code_timeago_tokens.trim_end().to_owned() + "\n }\n}\n";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
mod abtest;
|
mod abtest;
|
||||||
mod collect_album_types;
|
mod collect_album_types;
|
||||||
|
mod collect_datetimes;
|
||||||
mod collect_large_numbers;
|
mod collect_large_numbers;
|
||||||
mod collect_playlist_dates;
|
mod collect_playlist_dates;
|
||||||
mod download_testfiles;
|
mod download_testfiles;
|
||||||
|
@ -26,9 +27,11 @@ enum Commands {
|
||||||
CollectPlaylistDates,
|
CollectPlaylistDates,
|
||||||
CollectLargeNumbers,
|
CollectLargeNumbers,
|
||||||
CollectAlbumTypes,
|
CollectAlbumTypes,
|
||||||
|
CollectDatetimes,
|
||||||
ParsePlaylistDates,
|
ParsePlaylistDates,
|
||||||
ParseLargeNumbers,
|
ParseLargeNumbers,
|
||||||
ParseAlbumTypes,
|
ParseAlbumTypes,
|
||||||
|
ParseDatetimes,
|
||||||
GenLocales,
|
GenLocales,
|
||||||
GenDict,
|
GenDict,
|
||||||
DownloadTestfiles,
|
DownloadTestfiles,
|
||||||
|
@ -55,6 +58,9 @@ async fn main() {
|
||||||
Commands::CollectAlbumTypes => {
|
Commands::CollectAlbumTypes => {
|
||||||
collect_album_types::collect_album_types(&cli.project_root, cli.concurrency).await;
|
collect_album_types::collect_album_types(&cli.project_root, cli.concurrency).await;
|
||||||
}
|
}
|
||||||
|
Commands::CollectDatetimes => {
|
||||||
|
collect_datetimes::collect_datetimes(&cli.project_root, cli.concurrency).await;
|
||||||
|
}
|
||||||
Commands::ParsePlaylistDates => {
|
Commands::ParsePlaylistDates => {
|
||||||
collect_playlist_dates::write_samples_to_dict(&cli.project_root)
|
collect_playlist_dates::write_samples_to_dict(&cli.project_root)
|
||||||
}
|
}
|
||||||
|
@ -62,6 +68,7 @@ async fn main() {
|
||||||
collect_large_numbers::write_samples_to_dict(&cli.project_root)
|
collect_large_numbers::write_samples_to_dict(&cli.project_root)
|
||||||
}
|
}
|
||||||
Commands::ParseAlbumTypes => collect_album_types::write_samples_to_dict(&cli.project_root),
|
Commands::ParseAlbumTypes => collect_album_types::write_samples_to_dict(&cli.project_root),
|
||||||
|
Commands::ParseDatetimes => collect_datetimes::write_samples_to_dict(&cli.project_root),
|
||||||
Commands::GenLocales => {
|
Commands::GenLocales => {
|
||||||
gen_locales::generate_locales(&cli.project_root).await;
|
gen_locales::generate_locales(&cli.project_root).await;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,14 @@ pub struct DictEntry {
|
||||||
/// - 03.01.2020 => `"DMY"`
|
/// - 03.01.2020 => `"DMY"`
|
||||||
/// - Jan 3, 2020 => `"DY"`
|
/// - Jan 3, 2020 => `"DY"`
|
||||||
pub date_order: String,
|
pub date_order: String,
|
||||||
|
/// Order in which to parse datetimes. Formatted as a string of
|
||||||
|
/// date/time identifiers (Y, y, M, D, H, h, m).
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
///
|
||||||
|
/// - 2023-04-14 15:00 => `"YMDHm"`
|
||||||
|
/// - 4/14/23, 3:00 PM => `"MDyhm"`
|
||||||
|
pub datetime_order: String,
|
||||||
/// Tokens for parsing month names.
|
/// Tokens for parsing month names.
|
||||||
///
|
///
|
||||||
/// Format: Parsed token -> Month number (starting from 1)
|
/// Format: Parsed token -> Month number (starting from 1)
|
||||||
|
|
231
src/client/channel_tv.rs
Normal file
231
src/client/channel_tv.rs
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
use super::{
|
||||||
|
response,
|
||||||
|
response::video_item::{IsLive, IsShort, IsUpcoming},
|
||||||
|
ClientType, MapResponse, QBrowse, RustyPipeQuery,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
error::{Error, ExtractionError},
|
||||||
|
model::{ChannelTag, ChannelTv, Verification, VideoItem},
|
||||||
|
param::Language,
|
||||||
|
serializer::MapResult,
|
||||||
|
timeago,
|
||||||
|
util::{self, TryRemove},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl RustyPipeQuery {
|
||||||
|
/// Get the latest videos of a YouTube channel using the SmartTV client
|
||||||
|
pub async fn channel_tv<S: AsRef<str>>(&self, channel_id: S) -> Result<ChannelTv, Error> {
|
||||||
|
let channel_id = channel_id.as_ref();
|
||||||
|
let context = self.get_context(ClientType::TvHtml5, true, None).await;
|
||||||
|
let request_body = QBrowse {
|
||||||
|
browse_id: channel_id,
|
||||||
|
context,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.execute_request::<response::ChannelTv, _, _>(
|
||||||
|
ClientType::TvHtml5,
|
||||||
|
"channel_tv",
|
||||||
|
channel_id.as_ref(),
|
||||||
|
"browse",
|
||||||
|
&request_body,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MapResponse<ChannelTv> for response::ChannelTv {
|
||||||
|
fn map_response(
|
||||||
|
self,
|
||||||
|
id: &str,
|
||||||
|
lang: Language,
|
||||||
|
_deobf: Option<&crate::deobfuscate::DeobfData>,
|
||||||
|
) -> Result<MapResult<ChannelTv>, ExtractionError> {
|
||||||
|
// dbg!(&self);
|
||||||
|
|
||||||
|
let cr = self
|
||||||
|
.contents
|
||||||
|
.tv_browse_renderer
|
||||||
|
.content
|
||||||
|
.tv_surface_content_renderer;
|
||||||
|
|
||||||
|
let header = cr.header.tv_surface_header_renderer;
|
||||||
|
let content = cr.content.section_list_renderer.contents;
|
||||||
|
|
||||||
|
let subscribe_btn = header.buttons.into_iter().next();
|
||||||
|
let subscriber_count = subscribe_btn
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|b| b.subscribe_button_renderer.subscriber_count_text.as_deref())
|
||||||
|
.and_then(|txt| util::parse_large_numstr(txt, lang));
|
||||||
|
let channel_id = subscribe_btn
|
||||||
|
.map(|b| b.subscribe_button_renderer.channel_id)
|
||||||
|
.unwrap_or_else(|| id.to_owned());
|
||||||
|
|
||||||
|
let uploads = content.into_iter().find(|shelf| {
|
||||||
|
shelf
|
||||||
|
.shelf_renderer
|
||||||
|
.endpoint
|
||||||
|
.browse_endpoint
|
||||||
|
.as_ref()
|
||||||
|
.map(|ep| ep.params == "EgZ2aWRlb3MYAyAAcADyBgsKCToCCAGiAQIIAQ%3D%3D")
|
||||||
|
.unwrap_or_default()
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut warnings = Vec::new();
|
||||||
|
let videos = uploads
|
||||||
|
.map(|uploads| {
|
||||||
|
let mut items = uploads
|
||||||
|
.shelf_renderer
|
||||||
|
.content
|
||||||
|
.horizontal_list_renderer
|
||||||
|
.items;
|
||||||
|
warnings.append(&mut items.warnings);
|
||||||
|
|
||||||
|
items
|
||||||
|
.c
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|v| {
|
||||||
|
let v = v.tile_renderer;
|
||||||
|
|
||||||
|
match v.content_type {
|
||||||
|
response::channel_tv::ContentType::Video => {
|
||||||
|
let h = v.header.tile_header_renderer;
|
||||||
|
let mut m = v.metadata.tile_metadata_renderer;
|
||||||
|
|
||||||
|
let length = h.thumbnail_overlays.first().and_then(|overlay| {
|
||||||
|
util::parse_video_length(
|
||||||
|
&overlay.thumbnail_overlay_time_status_renderer.text,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let is_upcoming = h.thumbnail_overlays.is_upcoming();
|
||||||
|
|
||||||
|
// Normal video:
|
||||||
|
// Line1: "Channel name", Line2: "View count" "•" "Upload date"
|
||||||
|
// Current stream:
|
||||||
|
// Line1: "Channel name", Line2: "10k watching"
|
||||||
|
// Upcoming stream:
|
||||||
|
// Line1: "Channel name", Line2: "Scheduled for 4/15/23, 12:00 AM"
|
||||||
|
let (view_count, publish_date_txt) = m
|
||||||
|
.lines
|
||||||
|
.try_swap_remove(1)
|
||||||
|
.map(|mut line| {
|
||||||
|
let date_i = if is_upcoming { 0 } else { 2 };
|
||||||
|
|
||||||
|
let view_count =
|
||||||
|
line.line_renderer.items.get(0).and_then(|vc| {
|
||||||
|
util::parse_large_numstr(
|
||||||
|
&vc.line_item_renderer.text,
|
||||||
|
lang,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let publish_date_txt = line
|
||||||
|
.line_renderer
|
||||||
|
.items
|
||||||
|
.try_swap_remove(date_i)
|
||||||
|
.map(|dt| dt.line_item_renderer.text);
|
||||||
|
(view_count, publish_date_txt)
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let publish_date = publish_date_txt.as_deref().and_then(|txt| {
|
||||||
|
if is_upcoming {
|
||||||
|
timeago::parse_datetime_or_warn(lang, txt, &mut warnings)
|
||||||
|
} else {
|
||||||
|
timeago::parse_textual_date_or_warn(
|
||||||
|
lang,
|
||||||
|
txt,
|
||||||
|
&mut warnings,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(VideoItem {
|
||||||
|
id: v.content_id,
|
||||||
|
name: m.title,
|
||||||
|
length,
|
||||||
|
thumbnail: h.thumbnail.into(),
|
||||||
|
channel: Some(ChannelTag {
|
||||||
|
id: channel_id.to_owned(),
|
||||||
|
name: header.title.to_owned(),
|
||||||
|
avatar: Vec::new(),
|
||||||
|
verification: Verification::None,
|
||||||
|
subscriber_count,
|
||||||
|
}),
|
||||||
|
publish_date,
|
||||||
|
publish_date_txt,
|
||||||
|
view_count,
|
||||||
|
is_live: h.thumbnail_overlays.is_live(),
|
||||||
|
is_short: h.thumbnail_overlays.is_short(),
|
||||||
|
is_upcoming,
|
||||||
|
short_description: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
Ok(MapResult {
|
||||||
|
c: ChannelTv {
|
||||||
|
id: channel_id,
|
||||||
|
name: header.title,
|
||||||
|
subscriber_count,
|
||||||
|
avatar: header.thumbnail.into(),
|
||||||
|
tv_banner: header.banner.into(),
|
||||||
|
videos,
|
||||||
|
visitor_data: self.response_context.visitor_data,
|
||||||
|
},
|
||||||
|
warnings,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::{fs::File, io::BufReader};
|
||||||
|
|
||||||
|
use path_macro::path;
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
client::{response, MapResponse},
|
||||||
|
model::ChannelTv,
|
||||||
|
param::Language,
|
||||||
|
serializer::MapResult,
|
||||||
|
util::tests::TESTFILES,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case::base("base", "UCXuqSBlHAE6Xw-yeJA0Tunw")]
|
||||||
|
#[case::music("music", "UC_vmjW5e1xEHhYjY2a0kK1A")]
|
||||||
|
#[case::live("live", "UCSJ4gkVC6NrvII8umztf0Ow")]
|
||||||
|
#[case::live_upcoming("live_upcoming", "UC9CoZyztR-8Xok8Pptzpq1Q")]
|
||||||
|
#[case::onevideo("onevideo", "UCAkeE1thnToEXZTao-CZkHw")]
|
||||||
|
fn map_channel_videos(#[case] name: &str, #[case] id: &str) {
|
||||||
|
let json_path = path!(*TESTFILES / "channel_tv" / format!("{name}.json"));
|
||||||
|
let json_file = File::open(json_path).unwrap();
|
||||||
|
|
||||||
|
let channel: response::ChannelTv =
|
||||||
|
serde_json::from_reader(BufReader::new(json_file)).unwrap();
|
||||||
|
let map_res: MapResult<ChannelTv> = channel.map_response(id, Language::En, None).unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
map_res.warnings.is_empty(),
|
||||||
|
"deserialization/mapping warnings: {:?}",
|
||||||
|
map_res.warnings
|
||||||
|
);
|
||||||
|
|
||||||
|
if name == "live_upcoming" {
|
||||||
|
insta::assert_ron_snapshot!(format!("map_channel_{name}"), map_res.c, {
|
||||||
|
".videos[1:].publish_date" => "[date]",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
insta::assert_ron_snapshot!(format!("map_channel_{name}"), map_res.c, {
|
||||||
|
".videos[].publish_date" => "[date]",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
pub(crate) mod response;
|
pub(crate) mod response;
|
||||||
|
|
||||||
mod channel;
|
mod channel;
|
||||||
|
mod channel_tv;
|
||||||
mod music_artist;
|
mod music_artist;
|
||||||
mod music_charts;
|
mod music_charts;
|
||||||
mod music_details;
|
mod music_details;
|
||||||
|
@ -57,15 +58,17 @@ pub enum ClientType {
|
||||||
///
|
///
|
||||||
/// can access YTM-specific data, cannot access non-music content
|
/// can access YTM-specific data, cannot access non-music content
|
||||||
DesktopMusic,
|
DesktopMusic,
|
||||||
/// used by Smart TVs
|
/// Client used by Smart TVs (youtube.com/tv)
|
||||||
|
TvHtml5,
|
||||||
|
/// Client used by the embedded player for Smart TVs
|
||||||
///
|
///
|
||||||
/// can access age-restricted videos, cannot access non-embeddable videos
|
/// can access age-restricted videos, cannot access non-embeddable videos
|
||||||
TvHtml5Embed,
|
TvHtml5Embed,
|
||||||
/// used by the Android app
|
/// Client used by the Android app
|
||||||
///
|
///
|
||||||
/// no obfuscated stream URLs, includes lower resolution audio streams
|
/// no obfuscated stream URLs, includes lower resolution audio streams
|
||||||
Android,
|
Android,
|
||||||
/// used by the iOS app
|
/// Client used by the iOS app
|
||||||
///
|
///
|
||||||
/// no obfuscated stream URLs
|
/// no obfuscated stream URLs
|
||||||
Ios,
|
Ios,
|
||||||
|
@ -74,7 +77,10 @@ pub enum ClientType {
|
||||||
impl ClientType {
|
impl ClientType {
|
||||||
fn is_web(&self) -> bool {
|
fn is_web(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
ClientType::Desktop | ClientType::DesktopMusic | ClientType::TvHtml5Embed => true,
|
ClientType::Desktop
|
||||||
|
| ClientType::DesktopMusic
|
||||||
|
| ClientType::TvHtml5
|
||||||
|
| ClientType::TvHtml5Embed => true,
|
||||||
ClientType::Android | ClientType::Ios => false,
|
ClientType::Android | ClientType::Ios => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,6 +116,26 @@ struct ClientInfo<'a> {
|
||||||
visitor_data: Option<&'a str>,
|
visitor_data: Option<&'a str>,
|
||||||
hl: Language,
|
hl: Language,
|
||||||
gl: Country,
|
gl: Country,
|
||||||
|
time_zone: &'a str,
|
||||||
|
utc_offset_minutes: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ClientInfo<'_> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
client_name: Default::default(),
|
||||||
|
client_version: Default::default(),
|
||||||
|
client_screen: None,
|
||||||
|
device_model: None,
|
||||||
|
platform: Default::default(),
|
||||||
|
original_url: None,
|
||||||
|
visitor_data: None,
|
||||||
|
hl: Language::En,
|
||||||
|
gl: Country::Us,
|
||||||
|
time_zone: "UTC",
|
||||||
|
utc_offset_minutes: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
@ -174,12 +200,19 @@ const YOUTUBE_MUSIC_HOME_URL: &str = "https://music.youtube.com/";
|
||||||
|
|
||||||
const DISABLE_PRETTY_PRINT_PARAMETER: &str = "&prettyPrint=false";
|
const DISABLE_PRETTY_PRINT_PARAMETER: &str = "&prettyPrint=false";
|
||||||
|
|
||||||
|
// Desktop client
|
||||||
const DESKTOP_CLIENT_VERSION: &str = "2.20230126.00.00";
|
const DESKTOP_CLIENT_VERSION: &str = "2.20230126.00.00";
|
||||||
const DESKTOP_API_KEY: &str = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
const DESKTOP_API_KEY: &str = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
||||||
const TVHTML5_CLIENT_VERSION: &str = "2.0";
|
|
||||||
const DESKTOP_MUSIC_API_KEY: &str = "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30";
|
const DESKTOP_MUSIC_API_KEY: &str = "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30";
|
||||||
const DESKTOP_MUSIC_CLIENT_VERSION: &str = "1.20230123.01.01";
|
const DESKTOP_MUSIC_CLIENT_VERSION: &str = "1.20230123.01.01";
|
||||||
|
|
||||||
|
// TV client
|
||||||
|
const TVHTML5_UA: &str = "Mozilla/5.0 (SMART-TV; LINUX; Tizen 5.5) AppleWebKit/537.36 (KHTML, like Gecko) 69.0.3497.106.1/5.5 TV Safari/537.36";
|
||||||
|
const TVHTML5_API_KEY: &str = "AIzaSyDCU8hByM-4DrUqRUYnGn-3llEO78bcxq8";
|
||||||
|
const TVHTML5_CLIENT_VERSION: &str = "7.20230412.04.00";
|
||||||
|
const TVHTML5_EMBED_CLIENT_VERSION: &str = "2.0";
|
||||||
|
|
||||||
|
// Mobile client
|
||||||
const MOBILE_CLIENT_VERSION: &str = "18.03.33";
|
const MOBILE_CLIENT_VERSION: &str = "18.03.33";
|
||||||
const ANDROID_API_KEY: &str = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w";
|
const ANDROID_API_KEY: &str = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w";
|
||||||
const IOS_API_KEY: &str = "AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc";
|
const IOS_API_KEY: &str = "AIzaSyB-63vPrdThhKuerbB2N_l7Kwwcxj6yUAc";
|
||||||
|
@ -252,13 +285,16 @@ impl Default for RustyPipeOpts {
|
||||||
struct CacheHolder {
|
struct CacheHolder {
|
||||||
desktop_client: RwLock<CacheEntry<ClientData>>,
|
desktop_client: RwLock<CacheEntry<ClientData>>,
|
||||||
music_client: RwLock<CacheEntry<ClientData>>,
|
music_client: RwLock<CacheEntry<ClientData>>,
|
||||||
|
tv_client: RwLock<CacheEntry<ClientData>>,
|
||||||
deobf: RwLock<CacheEntry<DeobfData>>,
|
deobf: RwLock<CacheEntry<DeobfData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
struct CacheData {
|
struct CacheData {
|
||||||
desktop_client: CacheEntry<ClientData>,
|
desktop_client: CacheEntry<ClientData>,
|
||||||
music_client: CacheEntry<ClientData>,
|
music_client: CacheEntry<ClientData>,
|
||||||
|
tv_client: CacheEntry<ClientData>,
|
||||||
deobf: CacheEntry<DeobfData>,
|
deobf: CacheEntry<DeobfData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,6 +400,7 @@ impl RustyPipeBuilder {
|
||||||
cache: CacheHolder {
|
cache: CacheHolder {
|
||||||
desktop_client: RwLock::new(cdata.desktop_client),
|
desktop_client: RwLock::new(cdata.desktop_client),
|
||||||
music_client: RwLock::new(cdata.music_client),
|
music_client: RwLock::new(cdata.music_client),
|
||||||
|
tv_client: RwLock::new(cdata.tv_client),
|
||||||
deobf: RwLock::new(cdata.deobf),
|
deobf: RwLock::new(cdata.deobf),
|
||||||
},
|
},
|
||||||
default_opts: self.default_opts,
|
default_opts: self.default_opts,
|
||||||
|
@ -558,61 +595,47 @@ impl RustyPipe {
|
||||||
|
|
||||||
/// Extract the current version of the YouTube desktop client from the website.
|
/// Extract the current version of the YouTube desktop client from the website.
|
||||||
async fn extract_desktop_client_version(&self) -> Result<String, Error> {
|
async fn extract_desktop_client_version(&self) -> Result<String, Error> {
|
||||||
let from_swjs = async {
|
self.extract_client_version(
|
||||||
let swjs = self
|
Some("https://www.youtube.com/sw.js"),
|
||||||
.http_request_txt(
|
"https://www.youtube.com/results?search_query=",
|
||||||
self.inner
|
"https://www.youtube.com",
|
||||||
.http
|
None,
|
||||||
.get("https://www.youtube.com/sw.js")
|
)
|
||||||
.header(header::ORIGIN, "https://www.youtube.com")
|
.await
|
||||||
.header(header::REFERER, "https://www.youtube.com")
|
|
||||||
.header(header::COOKIE, self.inner.consent_cookie.to_owned())
|
|
||||||
.build()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
util::get_cg_from_regexes(CLIENT_VERSION_REGEXES.iter(), &swjs, 1).ok_or(
|
|
||||||
Error::Extraction(ExtractionError::InvalidData(Cow::Borrowed(
|
|
||||||
"Could not find desktop client version in sw.js",
|
|
||||||
))),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let from_html = async {
|
|
||||||
let html = self
|
|
||||||
.http_request_txt(
|
|
||||||
self.inner
|
|
||||||
.http
|
|
||||||
.get("https://www.youtube.com/results?search_query=")
|
|
||||||
.build()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
util::get_cg_from_regexes(CLIENT_VERSION_REGEXES.iter(), &html, 1).ok_or(
|
|
||||||
Error::Extraction(ExtractionError::InvalidData(Cow::Borrowed(
|
|
||||||
"Could not find desktop client version on html page",
|
|
||||||
))),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
match from_swjs.await {
|
|
||||||
Ok(client_version) => Ok(client_version),
|
|
||||||
Err(_) => from_html.await,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the current version of the YouTube Music desktop client from the website.
|
/// Extract the current version of the YouTube Music desktop client from the website.
|
||||||
async fn extract_music_client_version(&self) -> Result<String, Error> {
|
async fn extract_music_client_version(&self) -> Result<String, Error> {
|
||||||
let from_swjs = async {
|
self.extract_client_version(
|
||||||
|
Some("https://music.youtube.com/sw.js"),
|
||||||
|
"https://music.youtube.com",
|
||||||
|
"https://music.youtube.com",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract the current version of the YouTube Music TV client from the website.
|
||||||
|
async fn extract_tv_client_version(&self) -> Result<String, Error> {
|
||||||
|
self.extract_client_version(None, "https://www.youtube.com/tv", "", Some(TVHTML5_UA))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn extract_client_version(
|
||||||
|
&self,
|
||||||
|
sw_url: Option<&str>,
|
||||||
|
html_url: &str,
|
||||||
|
origin: &str,
|
||||||
|
ua: Option<&str>,
|
||||||
|
) -> Result<String, Error> {
|
||||||
|
let from_swjs = sw_url.map(|sw_url| async move {
|
||||||
let swjs = self
|
let swjs = self
|
||||||
.http_request_txt(
|
.http_request_txt(
|
||||||
self.inner
|
self.inner
|
||||||
.http
|
.http
|
||||||
.get("https://music.youtube.com/sw.js")
|
.get(sw_url)
|
||||||
.header(header::ORIGIN, "https://music.youtube.com")
|
.header(header::ORIGIN, origin)
|
||||||
.header(header::REFERER, "https://music.youtube.com")
|
.header(header::REFERER, origin)
|
||||||
.header(header::COOKIE, self.inner.consent_cookie.to_owned())
|
.header(header::COOKIE, self.inner.consent_cookie.to_owned())
|
||||||
.build()
|
.build()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
@ -621,32 +644,33 @@ impl RustyPipe {
|
||||||
|
|
||||||
util::get_cg_from_regexes(CLIENT_VERSION_REGEXES.iter(), &swjs, 1).ok_or(
|
util::get_cg_from_regexes(CLIENT_VERSION_REGEXES.iter(), &swjs, 1).ok_or(
|
||||||
Error::Extraction(ExtractionError::InvalidData(Cow::Borrowed(
|
Error::Extraction(ExtractionError::InvalidData(Cow::Borrowed(
|
||||||
"Could not find music client version in sw.js",
|
"Could not find client version in sw.js",
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
};
|
});
|
||||||
|
|
||||||
let from_html = async {
|
let from_html = async {
|
||||||
let html = self
|
let mut builder = self.inner.http.get(html_url);
|
||||||
.http_request_txt(
|
if let Some(ua) = ua {
|
||||||
self.inner
|
builder = builder.header(header::USER_AGENT, ua);
|
||||||
.http
|
}
|
||||||
.get("https://music.youtube.com")
|
|
||||||
.build()
|
let html = self.http_request_txt(builder.build().unwrap()).await?;
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
util::get_cg_from_regexes(CLIENT_VERSION_REGEXES.iter(), &html, 1).ok_or(
|
util::get_cg_from_regexes(CLIENT_VERSION_REGEXES.iter(), &html, 1).ok_or(
|
||||||
Error::Extraction(ExtractionError::InvalidData(Cow::Borrowed(
|
Error::Extraction(ExtractionError::InvalidData(Cow::Borrowed(
|
||||||
"Could not find music client version on html page",
|
"Could not find client version on html page",
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
match from_swjs.await {
|
if let Some(from_swjs) = from_swjs {
|
||||||
Ok(client_version) => Ok(client_version),
|
match from_swjs.await {
|
||||||
Err(_) => from_html.await,
|
Ok(client_version) => Ok(client_version),
|
||||||
|
Err(_) => from_html.await,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
from_html.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,7 +698,7 @@ impl RustyPipe {
|
||||||
version
|
version
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("{}, falling back to hardcoded version", e);
|
log::warn!("{}, falling back to hardcoded desktop client version", e);
|
||||||
DESKTOP_CLIENT_VERSION.to_owned()
|
DESKTOP_CLIENT_VERSION.to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -706,7 +730,7 @@ impl RustyPipe {
|
||||||
version
|
version
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("{}, falling back to hardcoded version", e);
|
log::warn!("{}, falling back to hardcoded music client version", e);
|
||||||
DESKTOP_MUSIC_CLIENT_VERSION.to_owned()
|
DESKTOP_MUSIC_CLIENT_VERSION.to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,6 +738,37 @@ impl RustyPipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current version of the YouTube TV client from the following sources
|
||||||
|
///
|
||||||
|
/// 1. from cache
|
||||||
|
/// 2. from the YouTube TV website
|
||||||
|
/// 3. fall back to the hardcoded version
|
||||||
|
async fn get_tv_client_version(&self) -> String {
|
||||||
|
// Write lock here to prevent concurrent tasks from fetching the same data
|
||||||
|
let mut tv_client = self.inner.cache.tv_client.write().await;
|
||||||
|
|
||||||
|
match tv_client.get() {
|
||||||
|
Some(cdata) => cdata.version.to_owned(),
|
||||||
|
None => {
|
||||||
|
log::debug!("getting tv client version");
|
||||||
|
match self.extract_tv_client_version().await {
|
||||||
|
Ok(version) => {
|
||||||
|
*tv_client = CacheEntry::from(ClientData {
|
||||||
|
version: version.to_owned(),
|
||||||
|
});
|
||||||
|
drop(tv_client);
|
||||||
|
self.store_cache().await;
|
||||||
|
version
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("{}, falling back to hardcoded tv client version", e);
|
||||||
|
TVHTML5_CLIENT_VERSION.to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Instantiate a new deobfuscator from either cached or extracted YouTube JavaScript code.
|
/// Instantiate a new deobfuscator from either cached or extracted YouTube JavaScript code.
|
||||||
async fn get_deobf_data(&self) -> Result<DeobfData, Error> {
|
async fn get_deobf_data(&self) -> Result<DeobfData, Error> {
|
||||||
// Write lock here to prevent concurrent tasks from fetching the same data
|
// Write lock here to prevent concurrent tasks from fetching the same data
|
||||||
|
@ -732,12 +787,13 @@ impl RustyPipe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the given cache data to the storage backend.
|
/// Write the current cache data to the storage backend.
|
||||||
async fn store_cache(&self) {
|
async fn store_cache(&self) {
|
||||||
if let Some(storage) = &self.inner.storage {
|
if let Some(storage) = &self.inner.storage {
|
||||||
let cdata = CacheData {
|
let cdata = CacheData {
|
||||||
desktop_client: self.inner.cache.desktop_client.read().await.clone(),
|
desktop_client: self.inner.cache.desktop_client.read().await.clone(),
|
||||||
music_client: self.inner.cache.music_client.read().await.clone(),
|
music_client: self.inner.cache.music_client.read().await.clone(),
|
||||||
|
tv_client: self.inner.cache.tv_client.read().await.clone(),
|
||||||
deobf: self.inner.cache.deobf.read().await.clone(),
|
deobf: self.inner.cache.deobf.read().await.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -838,13 +894,12 @@ impl RustyPipeQuery {
|
||||||
client: ClientInfo {
|
client: ClientInfo {
|
||||||
client_name: "WEB",
|
client_name: "WEB",
|
||||||
client_version: Cow::Owned(self.client.get_desktop_client_version().await),
|
client_version: Cow::Owned(self.client.get_desktop_client_version().await),
|
||||||
client_screen: None,
|
|
||||||
device_model: None,
|
|
||||||
platform: "DESKTOP",
|
platform: "DESKTOP",
|
||||||
original_url: Some("https://www.youtube.com/"),
|
original_url: Some("https://www.youtube.com/"),
|
||||||
visitor_data,
|
visitor_data,
|
||||||
hl,
|
hl,
|
||||||
gl,
|
gl,
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
request: Some(RequestYT::default()),
|
request: Some(RequestYT::default()),
|
||||||
user: User::default(),
|
user: User::default(),
|
||||||
|
@ -854,13 +909,29 @@ impl RustyPipeQuery {
|
||||||
client: ClientInfo {
|
client: ClientInfo {
|
||||||
client_name: "WEB_REMIX",
|
client_name: "WEB_REMIX",
|
||||||
client_version: Cow::Owned(self.client.get_music_client_version().await),
|
client_version: Cow::Owned(self.client.get_music_client_version().await),
|
||||||
client_screen: None,
|
|
||||||
device_model: None,
|
|
||||||
platform: "DESKTOP",
|
platform: "DESKTOP",
|
||||||
original_url: Some("https://music.youtube.com/"),
|
original_url: Some("https://music.youtube.com/"),
|
||||||
visitor_data,
|
visitor_data,
|
||||||
hl,
|
hl,
|
||||||
gl,
|
gl,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
request: Some(RequestYT::default()),
|
||||||
|
user: User::default(),
|
||||||
|
third_party: None,
|
||||||
|
},
|
||||||
|
ClientType::TvHtml5 => YTContext {
|
||||||
|
client: ClientInfo {
|
||||||
|
client_name: "TVHTML5",
|
||||||
|
client_version: Cow::Owned(self.client.get_tv_client_version().await),
|
||||||
|
client_screen: None,
|
||||||
|
device_model: Some("SmartTV"),
|
||||||
|
platform: "TV",
|
||||||
|
original_url: Some("https://www.youtube.com/tv"),
|
||||||
|
visitor_data,
|
||||||
|
hl,
|
||||||
|
gl,
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
request: Some(RequestYT::default()),
|
request: Some(RequestYT::default()),
|
||||||
user: User::default(),
|
user: User::default(),
|
||||||
|
@ -869,14 +940,13 @@ impl RustyPipeQuery {
|
||||||
ClientType::TvHtml5Embed => YTContext {
|
ClientType::TvHtml5Embed => YTContext {
|
||||||
client: ClientInfo {
|
client: ClientInfo {
|
||||||
client_name: "TVHTML5_SIMPLY_EMBEDDED_PLAYER",
|
client_name: "TVHTML5_SIMPLY_EMBEDDED_PLAYER",
|
||||||
client_version: Cow::Borrowed(TVHTML5_CLIENT_VERSION),
|
client_version: Cow::Borrowed(TVHTML5_EMBED_CLIENT_VERSION),
|
||||||
client_screen: Some("EMBED"),
|
client_screen: Some("EMBED"),
|
||||||
device_model: None,
|
|
||||||
platform: "TV",
|
platform: "TV",
|
||||||
original_url: None,
|
|
||||||
visitor_data,
|
visitor_data,
|
||||||
hl,
|
hl,
|
||||||
gl,
|
gl,
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
request: Some(RequestYT::default()),
|
request: Some(RequestYT::default()),
|
||||||
user: User::default(),
|
user: User::default(),
|
||||||
|
@ -888,13 +958,11 @@ impl RustyPipeQuery {
|
||||||
client: ClientInfo {
|
client: ClientInfo {
|
||||||
client_name: "ANDROID",
|
client_name: "ANDROID",
|
||||||
client_version: Cow::Borrowed(MOBILE_CLIENT_VERSION),
|
client_version: Cow::Borrowed(MOBILE_CLIENT_VERSION),
|
||||||
client_screen: None,
|
|
||||||
device_model: None,
|
|
||||||
platform: "MOBILE",
|
platform: "MOBILE",
|
||||||
original_url: None,
|
|
||||||
visitor_data,
|
visitor_data,
|
||||||
hl,
|
hl,
|
||||||
gl,
|
gl,
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
request: None,
|
request: None,
|
||||||
user: User::default(),
|
user: User::default(),
|
||||||
|
@ -904,13 +972,12 @@ impl RustyPipeQuery {
|
||||||
client: ClientInfo {
|
client: ClientInfo {
|
||||||
client_name: "IOS",
|
client_name: "IOS",
|
||||||
client_version: Cow::Borrowed(MOBILE_CLIENT_VERSION),
|
client_version: Cow::Borrowed(MOBILE_CLIENT_VERSION),
|
||||||
client_screen: None,
|
|
||||||
device_model: Some(IOS_DEVICE_MODEL),
|
device_model: Some(IOS_DEVICE_MODEL),
|
||||||
platform: "MOBILE",
|
platform: "MOBILE",
|
||||||
original_url: None,
|
|
||||||
visitor_data,
|
visitor_data,
|
||||||
hl,
|
hl,
|
||||||
gl,
|
gl,
|
||||||
|
..Default::default()
|
||||||
},
|
},
|
||||||
request: None,
|
request: None,
|
||||||
user: User::default(),
|
user: User::default(),
|
||||||
|
@ -958,6 +1025,17 @@ impl RustyPipeQuery {
|
||||||
"X-YouTube-Client-Version",
|
"X-YouTube-Client-Version",
|
||||||
self.client.get_music_client_version().await,
|
self.client.get_music_client_version().await,
|
||||||
),
|
),
|
||||||
|
ClientType::TvHtml5 => self
|
||||||
|
.client
|
||||||
|
.inner
|
||||||
|
.http
|
||||||
|
.post(format!(
|
||||||
|
"{YOUTUBEI_V1_URL}{endpoint}?key={TVHTML5_API_KEY}{DISABLE_PRETTY_PRINT_PARAMETER}"
|
||||||
|
))
|
||||||
|
.header(header::ORIGIN, "https://www.youtube.com")
|
||||||
|
.header(header::REFERER, "https://www.youtube.com/tv")
|
||||||
|
.header(header::USER_AGENT, TVHTML5_UA)
|
||||||
|
.header("X-YouTube-Client-Version", self.client.get_tv_client_version().await),
|
||||||
ClientType::TvHtml5Embed => self
|
ClientType::TvHtml5Embed => self
|
||||||
.client
|
.client
|
||||||
.inner
|
.inner
|
||||||
|
@ -968,7 +1046,7 @@ impl RustyPipeQuery {
|
||||||
.header(header::ORIGIN, "https://www.youtube.com")
|
.header(header::ORIGIN, "https://www.youtube.com")
|
||||||
.header(header::REFERER, "https://www.youtube.com")
|
.header(header::REFERER, "https://www.youtube.com")
|
||||||
.header("X-YouTube-Client-Name", "1")
|
.header("X-YouTube-Client-Name", "1")
|
||||||
.header("X-YouTube-Client-Version", TVHTML5_CLIENT_VERSION),
|
.header("X-YouTube-Client-Version", TVHTML5_EMBED_CLIENT_VERSION),
|
||||||
ClientType::Android => self
|
ClientType::Android => self
|
||||||
.client
|
.client
|
||||||
.inner
|
.inner
|
||||||
|
@ -1222,6 +1300,33 @@ fn validate_country(country: Country) -> Country {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
fn get_major_version(version: &str) -> u32 {
|
||||||
|
let parts = version.split('.').collect::<Vec<_>>();
|
||||||
|
assert_eq!(parts.len(), 4);
|
||||||
|
parts[0].parse().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t_extract_desktop_client_version() {
|
||||||
|
let rp = RustyPipe::new();
|
||||||
|
let version = tokio_test::block_on(rp.extract_desktop_client_version()).unwrap();
|
||||||
|
assert!(get_major_version(&version) >= 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t_extract_music_client_version() {
|
||||||
|
let rp = RustyPipe::new();
|
||||||
|
let version = tokio_test::block_on(rp.extract_music_client_version()).unwrap();
|
||||||
|
assert!(get_major_version(&version) >= 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t_extract_tv_client_version() {
|
||||||
|
let rp = RustyPipe::new();
|
||||||
|
let version = tokio_test::block_on(rp.extract_tv_client_version()).unwrap();
|
||||||
|
assert!(get_major_version(&version) >= 7);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn t_get_ytm_visitor_data() {
|
fn t_get_ytm_visitor_data() {
|
||||||
let rp = RustyPipe::new();
|
let rp = RustyPipe::new();
|
||||||
|
|
202
src/client/response/channel_tv.rs
Normal file
202
src/client/response/channel_tv.rs
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_with::{serde_as, VecSkipError};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
url_endpoint::NavigationEndpoint, video_item::TimeOverlay, ContentRenderer, ResponseContext,
|
||||||
|
Thumbnails,
|
||||||
|
};
|
||||||
|
use crate::serializer::{text::Text, MapResult, VecLogError};
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct ChannelTv {
|
||||||
|
pub contents: Contents,
|
||||||
|
pub response_context: ResponseContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct Contents {
|
||||||
|
pub tv_browse_renderer: ContentRenderer<TvSurface>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct TvSurface {
|
||||||
|
pub tv_surface_content_renderer: SurfaceContentRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct SurfaceContentRenderer {
|
||||||
|
#[serde(default)]
|
||||||
|
pub content: SurfaceContent,
|
||||||
|
pub header: SurfaceHeader,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct SurfaceHeader {
|
||||||
|
pub tv_surface_header_renderer: SurfaceHeaderRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct SurfaceHeaderRenderer {
|
||||||
|
// TODO: really?
|
||||||
|
// #[serde(default)]
|
||||||
|
#[serde_as(as = "Text")]
|
||||||
|
pub title: String,
|
||||||
|
/// Channel avatar
|
||||||
|
#[serde(default)]
|
||||||
|
pub thumbnail: Thumbnails,
|
||||||
|
#[serde(default)]
|
||||||
|
pub banner: Thumbnails,
|
||||||
|
#[serde_as(as = "VecSkipError<_>")]
|
||||||
|
pub buttons: Vec<SubscribeButton>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct SubscribeButton {
|
||||||
|
pub subscribe_button_renderer: SubscribeButtonRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct SubscribeButtonRenderer {
|
||||||
|
pub channel_id: String,
|
||||||
|
#[serde_as(as = "Option<Text>")]
|
||||||
|
pub subscriber_count_text: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct SurfaceContent {
|
||||||
|
pub section_list_renderer: SectionList,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Default, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct SectionList {
|
||||||
|
#[serde_as(as = "VecSkipError<_>")]
|
||||||
|
pub contents: Vec<Shelf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct Shelf {
|
||||||
|
pub shelf_renderer: ShelfRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct ShelfRenderer {
|
||||||
|
pub content: ShelfContent,
|
||||||
|
pub endpoint: NavigationEndpoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct ShelfContent {
|
||||||
|
pub horizontal_list_renderer: HorizontalListRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct HorizontalListRenderer {
|
||||||
|
#[serde_as(as = "VecLogError<_>")]
|
||||||
|
pub items: MapResult<Vec<Tile>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct Tile {
|
||||||
|
pub tile_renderer: TileRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct TileRenderer {
|
||||||
|
pub content_id: String,
|
||||||
|
pub content_type: ContentType,
|
||||||
|
pub header: TileHeader,
|
||||||
|
pub metadata: Metadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct TileHeader {
|
||||||
|
pub tile_header_renderer: TileHeaderRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct TileHeaderRenderer {
|
||||||
|
pub thumbnail: Thumbnails,
|
||||||
|
/// Contains Live tag
|
||||||
|
#[serde(default)]
|
||||||
|
#[serde_as(as = "VecSkipError<_>")]
|
||||||
|
pub thumbnail_overlays: Vec<TimeOverlay>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct Metadata {
|
||||||
|
pub tile_metadata_renderer: MetadataRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct MetadataRenderer {
|
||||||
|
#[serde_as(as = "Text")]
|
||||||
|
pub title: String,
|
||||||
|
#[serde(default)]
|
||||||
|
#[serde_as(as = "VecSkipError<_>")]
|
||||||
|
pub lines: Vec<Line>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct Line {
|
||||||
|
pub line_renderer: LineRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct LineRenderer {
|
||||||
|
#[serde_as(as = "VecSkipError<_>")]
|
||||||
|
pub items: Vec<LineItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct LineItem {
|
||||||
|
pub line_item_renderer: LineItemRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct LineItemRenderer {
|
||||||
|
#[serde_as(as = "Text")]
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub(crate) enum ContentType {
|
||||||
|
#[serde(rename = "TILE_CONTENT_TYPE_VIDEO")]
|
||||||
|
Video,
|
||||||
|
#[serde(rename = "TILE_CONTENT_TYPE_CHANNEL")]
|
||||||
|
Channel,
|
||||||
|
#[serde(rename = "TILE_CONTENT_TYPE_PLAYLIST")]
|
||||||
|
Playlist,
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub(crate) mod channel;
|
pub(crate) mod channel;
|
||||||
|
pub(crate) mod channel_tv;
|
||||||
pub(crate) mod music_artist;
|
pub(crate) mod music_artist;
|
||||||
pub(crate) mod music_charts;
|
pub(crate) mod music_charts;
|
||||||
pub(crate) mod music_details;
|
pub(crate) mod music_details;
|
||||||
|
@ -16,6 +17,7 @@ pub(crate) mod video_details;
|
||||||
pub(crate) mod video_item;
|
pub(crate) mod video_item;
|
||||||
|
|
||||||
pub(crate) use channel::Channel;
|
pub(crate) use channel::Channel;
|
||||||
|
pub(crate) use channel_tv::ChannelTv;
|
||||||
pub(crate) use music_artist::MusicArtist;
|
pub(crate) use music_artist::MusicArtist;
|
||||||
pub(crate) use music_artist::MusicArtistAlbums;
|
pub(crate) use music_artist::MusicArtistAlbums;
|
||||||
pub(crate) use music_charts::MusicCharts;
|
pub(crate) use music_charts::MusicCharts;
|
||||||
|
|
|
@ -273,6 +273,7 @@ pub(crate) enum TimeOverlayStyle {
|
||||||
Default,
|
Default,
|
||||||
Live,
|
Live,
|
||||||
Shorts,
|
Shorts,
|
||||||
|
Upcoming,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
|
@ -356,14 +357,18 @@ pub(crate) struct PrimaryLink {
|
||||||
pub navigation_endpoint: NavigationEndpoint,
|
pub navigation_endpoint: NavigationEndpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait IsLive {
|
pub(crate) trait IsLive {
|
||||||
fn is_live(&self) -> bool;
|
fn is_live(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait IsShort {
|
pub(crate) trait IsShort {
|
||||||
fn is_short(&self) -> bool;
|
fn is_short(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) trait IsUpcoming {
|
||||||
|
fn is_upcoming(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
impl IsLive for Vec<VideoBadge> {
|
impl IsLive for Vec<VideoBadge> {
|
||||||
fn is_live(&self) -> bool {
|
fn is_live(&self) -> bool {
|
||||||
self.iter().any(|badge| {
|
self.iter().any(|badge| {
|
||||||
|
@ -388,6 +393,14 @@ impl IsShort for Vec<TimeOverlay> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IsUpcoming for Vec<TimeOverlay> {
|
||||||
|
fn is_upcoming(&self) -> bool {
|
||||||
|
self.iter().any(|overlay| {
|
||||||
|
overlay.thumbnail_overlay_time_status_renderer.style == TimeOverlayStyle::Upcoming
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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)]
|
||||||
|
|
|
@ -0,0 +1,658 @@
|
||||||
|
---
|
||||||
|
source: src/client/channel_tv.rs
|
||||||
|
expression: map_res.c
|
||||||
|
---
|
||||||
|
ChannelTv(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
avatar: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/Vy6KL7EM_apxPSxF0pPy5w_c87YDTOlBQo3MADDF0Wl51kwxmt9wmRotnt2xQXwlrcyO0Xe56w=s72-c-k-c0x00ffffff-no-rj",
|
||||||
|
width: 72,
|
||||||
|
height: 72,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
tv_banner: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/ZM642NyuML42iPDUaopQKNyHmTbECQ87IRQ5EOpAmyLV8LnGT2h-D2DGV8zbO32P7ovliRtBNjY=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/ZM642NyuML42iPDUaopQKNyHmTbECQ87IRQ5EOpAmyLV8LnGT2h-D2DGV8zbO32P7ovliRtBNjY=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 854,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/ZM642NyuML42iPDUaopQKNyHmTbECQ87IRQ5EOpAmyLV8LnGT2h-D2DGV8zbO32P7ovliRtBNjY=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/ZM642NyuML42iPDUaopQKNyHmTbECQ87IRQ5EOpAmyLV8LnGT2h-D2DGV8zbO32P7ovliRtBNjY=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/ZM642NyuML42iPDUaopQKNyHmTbECQ87IRQ5EOpAmyLV8LnGT2h-D2DGV8zbO32P7ovliRtBNjY=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 2120,
|
||||||
|
height: 1192,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
videos: [
|
||||||
|
VideoItem(
|
||||||
|
id: "1vpepaQ-VQQ",
|
||||||
|
name: "STOP Buying ANDROID TV Boxes!",
|
||||||
|
length: Some(620),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1vpepaQ-VQQ/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1vpepaQ-VQQ/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1vpepaQ-VQQ/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBUaVN2jfJqIDmESCGLN7278aOFLw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1vpepaQ-VQQ/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1vpepaQ-VQQ/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1vpepaQ-VQQ/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("21 hours ago"),
|
||||||
|
view_count: Some(1200000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "nkh9VGCY8as",
|
||||||
|
name: "I’m Dreading this Review – RTX 4070",
|
||||||
|
length: Some(701),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nkh9VGCY8as/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nkh9VGCY8as/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nkh9VGCY8as/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLAXgvQB3T_twGIsf3AQdwGQl5G7Fg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nkh9VGCY8as/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nkh9VGCY8as/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nkh9VGCY8as/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("2 days ago"),
|
||||||
|
view_count: Some(1800000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "9hTYUHm3pKw",
|
||||||
|
name: "Giving out free tech tips AGAIN",
|
||||||
|
length: Some(36),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/9hTYUHm3pKw/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARhjIGMoYzAP&rs=AOn4CLCS7gCg5w_iExAOqftGiAQ8Wq_a2Q",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/9hTYUHm3pKw/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGMgYyhjMA8=&rs=AOn4CLB6z2XIAF9_wJ5KzE3yMjnreACxgQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/9hTYUHm3pKw/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYYyBjKGMwDw==&rs=AOn4CLBe_TI0cWb_PRKBrCr6TjpmETqZHA",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/9hTYUHm3pKw/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGMgYyhjMA8=&rs=AOn4CLDMuyrew8kihs0-SzA6HvYXCdOuqg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/9hTYUHm3pKw/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGMgYyhjMA8=&rs=AOn4CLBDgipAqpEfEBoi8lCVGt5DSlj0bA",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/9hTYUHm3pKw/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGMgYyhjMA8=&rs=AOn4CLDGQ6aAeJcPKhhboiUiY33OJNdLCw",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("2 days ago"),
|
||||||
|
view_count: Some(363000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "g7oNuP83VXs",
|
||||||
|
name: "The Amazon Basics CPU Cooler",
|
||||||
|
length: Some(500),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/g7oNuP83VXs/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/g7oNuP83VXs/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/g7oNuP83VXs/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLCko9k-lp8mijshkO--ADN2EVA7zQ",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/g7oNuP83VXs/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/g7oNuP83VXs/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/g7oNuP83VXs/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("2 days ago"),
|
||||||
|
view_count: Some(1000000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "LVkqK4bl1Gw",
|
||||||
|
name: "If you can fix this PC, it’s yours!",
|
||||||
|
length: Some(1325),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/LVkqK4bl1Gw/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/LVkqK4bl1Gw/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/LVkqK4bl1Gw/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBJRqXG5q_aXx2LgJoM2gnKJPcAug",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/LVkqK4bl1Gw/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/LVkqK4bl1Gw/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/LVkqK4bl1Gw/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("3 days ago"),
|
||||||
|
view_count: Some(1100000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "nLIp4wd0oXs",
|
||||||
|
name: "This Makes Hacking TOO Easy - Flipper Zero",
|
||||||
|
length: Some(732),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nLIp4wd0oXs/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nLIp4wd0oXs/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nLIp4wd0oXs/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBe8ewilB3sskZPwqG-XopT5T5tPw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nLIp4wd0oXs/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nLIp4wd0oXs/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nLIp4wd0oXs/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("4 days ago"),
|
||||||
|
view_count: Some(3100000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "1ugJ1BJx0HE",
|
||||||
|
name: "The SCAM of Wireless ESD Straps - Feat. ElectroBOOM",
|
||||||
|
length: Some(1763),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1ugJ1BJx0HE/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1ugJ1BJx0HE/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1ugJ1BJx0HE/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLA_7h5PVIjqmCDOFwN7kVFxuJP7sw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1ugJ1BJx0HE/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1ugJ1BJx0HE/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/1ugJ1BJx0HE/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("5 days ago"),
|
||||||
|
view_count: Some(2500000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "s-llzV_3LaE",
|
||||||
|
name: "A Monster Lawsuit Is Coming For Me - WAN Show April 7, 2023",
|
||||||
|
length: Some(18993),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/s-llzV_3LaE/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/s-llzV_3LaE/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/s-llzV_3LaE/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLB1s67Dq72qpCeHvyYbjzNiCr3INw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/s-llzV_3LaE/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/s-llzV_3LaE/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/s-llzV_3LaE/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("Streamed 6 days ago"),
|
||||||
|
view_count: Some(988000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "EzdV27b1V1Q",
|
||||||
|
name: "Does this ACTUALLY hurt your PC?",
|
||||||
|
length: Some(35),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/EzdV27b1V1Q/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARhlIFMoSjAP&rs=AOn4CLDZXi514ordaLSYrB-qaYZdsvJAEg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/EzdV27b1V1Q/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGUgUyhKMA8=&rs=AOn4CLA9miEzhK8HK_1WETFjVqgn0NtMNQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/EzdV27b1V1Q/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYZSBTKEowDw==&rs=AOn4CLAp25U83rZDwrUpogDGHYJjGaRI8g",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/EzdV27b1V1Q/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGUgUyhKMA8=&rs=AOn4CLC4XNTvkQt54_eREftUvCwStfJg1Q",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/EzdV27b1V1Q/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGUgUyhKMA8=&rs=AOn4CLD-vCRuPU9MqGMAQJ1K7Vxge-5_Zw",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/EzdV27b1V1Q/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGUgUyhKMA8=&rs=AOn4CLBRCNjDmhZlVjBAmpoVt3daA_BPog",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("6 days ago"),
|
||||||
|
view_count: Some(1300000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "k7wnNt65lcE",
|
||||||
|
name: "Can a Gaming PC Survive the North Pole?",
|
||||||
|
length: Some(1113),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k7wnNt65lcE/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k7wnNt65lcE/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k7wnNt65lcE/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBRrjrpo5NAGat65o1U2ec2G61HLw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k7wnNt65lcE/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k7wnNt65lcE/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k7wnNt65lcE/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("7 days ago"),
|
||||||
|
view_count: Some(1800000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "nj4gn7od0jY",
|
||||||
|
name: "It\'s the Best Gaming CPU on the Planet.. AND I\'M MAD. - Ryzen 7 7800X3D Review",
|
||||||
|
length: Some(823),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nj4gn7od0jY/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nj4gn7od0jY/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nj4gn7od0jY/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLDJXMMuyasfoq_dbMTcJW8px_vW4g",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nj4gn7od0jY/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nj4gn7od0jY/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nj4gn7od0jY/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("9 days ago"),
|
||||||
|
view_count: Some(1800000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "k_3NVXml470",
|
||||||
|
name: "No… THIS is the CLEANEST Setup",
|
||||||
|
length: Some(643),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k_3NVXml470/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k_3NVXml470/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k_3NVXml470/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBu3-leVqNCGsYN7_o7g5Ji8T3V7A",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k_3NVXml470/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k_3NVXml470/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/k_3NVXml470/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||||
|
name: "Linus Tech Tips",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(15400000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("9 days ago"),
|
||||||
|
view_count: Some(2900000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
visitor_data: Some("Cgs1UVZkeFlUN1ZXWSiWvuWhBg%3D%3D"),
|
||||||
|
)
|
|
@ -0,0 +1,658 @@
|
||||||
|
---
|
||||||
|
source: src/client/channel_tv.rs
|
||||||
|
expression: map_res.c
|
||||||
|
---
|
||||||
|
ChannelTv(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
avatar: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/gY8H7K-3Eg3olVftRBiqqFe-N5d9Rx90jAsrfQuxDa4m32Wm-kWK6AQJhwchvYLf-H4EjGhCSw=s72-c-k-c0x00ffffff-no-rj",
|
||||||
|
width: 72,
|
||||||
|
height: 72,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
tv_banner: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/X9zEVI1HRWuZ7gHhG9fv_4IjSLwJMdAadTuXfa2vMAHSAIun4s_e6TgNa1WQOr-f88SWbU1uuQ=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/X9zEVI1HRWuZ7gHhG9fv_4IjSLwJMdAadTuXfa2vMAHSAIun4s_e6TgNa1WQOr-f88SWbU1uuQ=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 854,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/X9zEVI1HRWuZ7gHhG9fv_4IjSLwJMdAadTuXfa2vMAHSAIun4s_e6TgNa1WQOr-f88SWbU1uuQ=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/X9zEVI1HRWuZ7gHhG9fv_4IjSLwJMdAadTuXfa2vMAHSAIun4s_e6TgNa1WQOr-f88SWbU1uuQ=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/X9zEVI1HRWuZ7gHhG9fv_4IjSLwJMdAadTuXfa2vMAHSAIun4s_e6TgNa1WQOr-f88SWbU1uuQ=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 2120,
|
||||||
|
height: 1192,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
videos: [
|
||||||
|
VideoItem(
|
||||||
|
id: "gVKsKpoPAYg",
|
||||||
|
name: "Synthwave Launch 🌌 - Lofi Girl POV",
|
||||||
|
length: Some(48),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/gVKsKpoPAYg/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBzgWAAoAKigIMCAAQARg8IEQocjAP&rs=AOn4CLAllPiZpD9AFINMDEjU5dZOzfwVUw",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/gVKsKpoPAYg/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AHOBYACgAqKAgwIABABGDwgRChyMA8=&rs=AOn4CLCWybBzmcom_-zoyu0Wg5wKLYO-uQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/gVKsKpoPAYg/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4Ac4FgAKACooCDAgAEAEYPCBEKHIwDw==&rs=AOn4CLBqWFhamy1_BSPTBz7TBig2dzmqNg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/gVKsKpoPAYg/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AHOBYACgAqKAgwIABABGDwgRChyMA8=&rs=AOn4CLDfQM-GAowYQlSB4XRG2oKf1SlJXQ",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/gVKsKpoPAYg/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AHOBYACgAqKAgwIABABGDwgRChyMA8=&rs=AOn4CLByedJwLMk68FhOb9QWoWNGbbSSbQ",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/gVKsKpoPAYg/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AHOBYACgAqKAgwIABABGDwgRChyMA8=&rs=AOn4CLARMx-s-uKPhUenIn33pO2_qfyFdQ",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("20 hours ago"),
|
||||||
|
view_count: Some(55000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "ZBh_mQl-2SQ",
|
||||||
|
name: "Synthwave Launch 🌌 - Lofi Boy POV",
|
||||||
|
length: Some(41),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZBh_mQl-2SQ/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgB_gmAAtAFigIMCAAQARguIDYofzAP&rs=AOn4CLDd4sv05hoiBIKRAT4PbLpmv8uBWQ",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZBh_mQl-2SQ/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGC4gNih_MA8=&rs=AOn4CLApfKBRT7E9k8AiNwYPZFeykDilWQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZBh_mQl-2SQ/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4Af4JgALQBYoCDAgAEAEYLiA2KH8wDw==&rs=AOn4CLAISEXvWDkxAQzzVQS4YDrxWTO6DA",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZBh_mQl-2SQ/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGC4gNih_MA8=&rs=AOn4CLAvnQlEavMwF9-RSpxIm8q_LeJqYA",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZBh_mQl-2SQ/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGC4gNih_MA8=&rs=AOn4CLDcXdJlM7-ynHW_MEuvsggZJLyk8w",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZBh_mQl-2SQ/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGC4gNih_MA8=&rs=AOn4CLDQsvu8EmLHSeE7O3_vdHqByo9qCQ",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("1 day ago"),
|
||||||
|
view_count: Some(420000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "b9IctXpyPCE",
|
||||||
|
name: "Synthwave Launch 🌌 - Lofi Girl POV",
|
||||||
|
length: Some(48),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/b9IctXpyPCE/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgB_gmAAtAFigIMCAAQARg-IDoofzAP&rs=AOn4CLCbXUK0zKikwTNK1vhXkHt3aJxCAA",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/b9IctXpyPCE/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGD4gOih_MA8=&rs=AOn4CLBk3cCVT11R8E7vhZpcRYkUL1q4Fw",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/b9IctXpyPCE/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4Af4JgALQBYoCDAgAEAEYPiA6KH8wDw==&rs=AOn4CLC5SevU_YD0sw_PB9ES21KwdD2-1Q",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/b9IctXpyPCE/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGD4gOih_MA8=&rs=AOn4CLDInx0-m4dL-8OgN_yWwF6ew-i2TQ",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/b9IctXpyPCE/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGD4gOih_MA8=&rs=AOn4CLDDjhE31W7dN0NlkPFylmTNvmFyyQ",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/b9IctXpyPCE/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGD4gOih_MA8=&rs=AOn4CLDde8MHooriWO6obGxSudvX3rcltA",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("1 day ago"),
|
||||||
|
view_count: Some(581000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "5cEPXBss8QM",
|
||||||
|
name: "What is happening with this blue window? 🤨",
|
||||||
|
length: Some(36),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/5cEPXBss8QM/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgB3ASAArgIigIMCAAQARhlIEAoSTAP&rs=AOn4CLAmZoxnBXD10_QWlTbkQiylMFQSRQ",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/5cEPXBss8QM/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AHcBIACuAiKAgwIABABGGUgQChJMA8=&rs=AOn4CLD6RBYAb-NAX3QXsiXkKS-wZIonqQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/5cEPXBss8QM/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AdwEgAK4CIoCDAgAEAEYZSBAKEkwDw==&rs=AOn4CLCI_0yo-jEjtLeazZk3joad3Pmv3Q",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/5cEPXBss8QM/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AHcBIACuAiKAgwIABABGGUgQChJMA8=&rs=AOn4CLAzagmNZtxPAzlHiIxyVPIIG6B69Q",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/5cEPXBss8QM/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AHcBIACuAiKAgwIABABGGUgQChJMA8=&rs=AOn4CLAMhY8RjaBMWNhz0U_D6uIeUyl59g",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/5cEPXBss8QM/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AHcBIACuAiKAgwIABABGGUgQChJMA8=&rs=AOn4CLD0NIOdYXyjktyYcIiI1ob2xTd3Xg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("6 days ago"),
|
||||||
|
view_count: Some(100000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "lvfI-9DMILA",
|
||||||
|
name: "What is happening with this blue window? 🤨",
|
||||||
|
length: Some(36),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lvfI-9DMILA/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lvfI-9DMILA/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lvfI-9DMILA/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLAE8Ufe-rHgTGAgVxR2DoVMm44wGA",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lvfI-9DMILA/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lvfI-9DMILA/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lvfI-9DMILA/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("6 days ago"),
|
||||||
|
view_count: Some(748000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "MVPTGNGiI-4",
|
||||||
|
name: "synthwave radio 🌌 - beats to chill/game to",
|
||||||
|
length: None,
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/MVPTGNGiI-4/default_live.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/MVPTGNGiI-4/mqdefault_live.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/MVPTGNGiI-4/hqdefault_live.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLDBtHLdfMneZyfYrENSn-Wt7C-vuQ",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/MVPTGNGiI-4/hqdefault_live.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/MVPTGNGiI-4/sddefault_live.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/MVPTGNGiI-4/maxresdefault_live.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(19000),
|
||||||
|
is_live: true,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "3CIVNxvQRzA",
|
||||||
|
name: "Lofi Girl finally stops studying 😱",
|
||||||
|
length: Some(8),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/3CIVNxvQRzA/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAv4OigIMCAAQARh_ID4oJjAP&rs=AOn4CLAE5Sc7TQs7igSxBU07H7NIIre4NA",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/3CIVNxvQRzA/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIAC_g6KAgwIABABGH8gPigmMA8=&rs=AOn4CLCMUGGdbhINd1WacSqRVinfbO0cyg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/3CIVNxvQRzA/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAL-DooCDAgAEAEYfyA-KCYwDw==&rs=AOn4CLAuS_30v--v1KGCzumWhEULTvLuJA",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/3CIVNxvQRzA/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIAC_g6KAgwIABABGH8gPigmMA8=&rs=AOn4CLBwf3ag6DantZd0_DXVLKyWe1zrIA",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/3CIVNxvQRzA/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIAC_g6KAgwIABABGH8gPigmMA8=&rs=AOn4CLAnwEsjw0bVV-rAM161dUE74fKrIg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/3CIVNxvQRzA/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIAC_g6KAgwIABABGH8gPigmMA8=&rs=AOn4CLC_RuPVKzI0RWNCicd81hSuWPhFbQ",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("12 days ago"),
|
||||||
|
view_count: Some(168000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "uHxgR7GzRNY",
|
||||||
|
name: "Lofi Girl finally stops studying 😱",
|
||||||
|
length: Some(148),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/uHxgR7GzRNY/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgB_gmAAtAFigIMCAAQARhyIEMoNTAP&rs=AOn4CLAR7wezefrApQ0aSxhGMXc-imbzeg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/uHxgR7GzRNY/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGHIgQyg1MA8=&rs=AOn4CLAopDnPneEkCVNJWHCjY8eGYzL5pQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/uHxgR7GzRNY/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4Af4JgALQBYoCDAgAEAEYciBDKDUwDw==&rs=AOn4CLDj0vLIiP1V1hPEK1cPMfSDzjrzSA",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/uHxgR7GzRNY/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGHIgQyg1MA8=&rs=AOn4CLDBw6HFU4g3fPo02jrq2-rEB-lZBA",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/uHxgR7GzRNY/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGHIgQyg1MA8=&rs=AOn4CLCqV5Jt-U3D09meQjnFjHTq5LS8XA",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/uHxgR7GzRNY/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGHIgQyg1MA8=&rs=AOn4CLBe8ct3EsMimsEFZdvo0SI0XYrCAw",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("12 days ago"),
|
||||||
|
view_count: Some(787000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "VrtXuFQLel8",
|
||||||
|
name: "Lofi Cat is love, Lofi Cat is life 🫶 ✨",
|
||||||
|
length: Some(7),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/VrtXuFQLel8/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARh_ICwoMDAP&rs=AOn4CLC6Y0PF2HDFqbBLcEEQrcy1YG3WuQ",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/VrtXuFQLel8/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gLCgwMA8=&rs=AOn4CLCf-XfwA3ePIcRFh_BlOkOcw_JfXQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/VrtXuFQLel8/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYfyAsKDAwDw==&rs=AOn4CLCeDpZ85ZEmzk1JfSS5nT3hf1bk9g",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/VrtXuFQLel8/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gLCgwMA8=&rs=AOn4CLA5m5PgHk5fpacw_-NW9HsB-8VyDw",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/VrtXuFQLel8/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gLCgwMA8=&rs=AOn4CLBtNdSVka23uytjitK2AuKNiEmVtA",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/VrtXuFQLel8/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gLCgwMA8=&rs=AOn4CLCUYKUjARNS-JW6u2pt8rHtmC_huA",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("2 weeks ago"),
|
||||||
|
view_count: Some(143000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "cCF0SNS26gc",
|
||||||
|
name: "When you’ve been studying for 5+ years… 🙄",
|
||||||
|
length: Some(8),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/cCF0SNS26gc/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARh_IEUoMTAP&rs=AOn4CLBL3KeYaYjrE4qX_1yeXMN7tWUmFw",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/cCF0SNS26gc/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gRSgxMA8=&rs=AOn4CLAYzqMqqDG3KrtwjhrbkxbbNaT5Bw",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/cCF0SNS26gc/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYfyBFKDEwDw==&rs=AOn4CLCKpJoGK7LcfqKjecX0Vw-F9OEVEg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/cCF0SNS26gc/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gRSgxMA8=&rs=AOn4CLCE9mgcI2iL21MOcrFIBatKrUxjLg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/cCF0SNS26gc/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gRSgxMA8=&rs=AOn4CLACrsY9egZ6YOOKAZtoTdKx3cRuiQ",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/cCF0SNS26gc/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gRSgxMA8=&rs=AOn4CLBr5xKlWjVwVEXlN7DwLMVDx8IN9A",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("3 weeks ago"),
|
||||||
|
view_count: Some(285000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "ywsXCTQ9vCI",
|
||||||
|
name: "I guess you’ve wondered where I’ve been 🌱💃",
|
||||||
|
length: Some(9),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ywsXCTQ9vCI/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARh_IEMoLTAP&rs=AOn4CLDuC4a7nRUlXlBFCv3pIbTxXRZVPw",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ywsXCTQ9vCI/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gQygtMA8=&rs=AOn4CLATDhHYdSI2zS2pykxNh_MPJCbQzw",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ywsXCTQ9vCI/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYfyBDKC0wDw==&rs=AOn4CLAUZw-rudW1_yzIocuXi_wcilFnVQ",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ywsXCTQ9vCI/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gQygtMA8=&rs=AOn4CLD3hdkjRKJ-SFkzUnk82Y7I0ZCTtQ",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ywsXCTQ9vCI/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gQygtMA8=&rs=AOn4CLDpODHlMHMb7MgOSSQOpM_hJUtGfg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ywsXCTQ9vCI/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGH8gQygtMA8=&rs=AOn4CLAK6jAEK0rfufMyY_rWRasU25dWHw",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("1 month ago"),
|
||||||
|
view_count: Some(513000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "Uzo6x3uwWRA",
|
||||||
|
name: "Get your own Lofi avatar merch now! 👕 (Link in comments 🔗)",
|
||||||
|
length: Some(25),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Uzo6x3uwWRA/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARhyIFcoQTAP&rs=AOn4CLAntbjIEzzY0MHNuV59m-iWn1VS_w",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Uzo6x3uwWRA/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGHIgVyhBMA8=&rs=AOn4CLCdoRffILQ3_rpwfQn5tn4SzWQDzw",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Uzo6x3uwWRA/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYciBXKEEwDw==&rs=AOn4CLBq_MQJHQdSx97dgT9OoAJByqVJcw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Uzo6x3uwWRA/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGHIgVyhBMA8=&rs=AOn4CLDxViAcvucN_oL0i1GNoHAp7o5MHQ",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Uzo6x3uwWRA/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGHIgVyhBMA8=&rs=AOn4CLAUSgHmTIlbT5BK8h43dw5WthNvwA",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Uzo6x3uwWRA/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGHIgVyhBMA8=&rs=AOn4CLBZN107K9EmsTktng19I_x78LrDwA",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCSJ4gkVC6NrvII8umztf0Ow",
|
||||||
|
name: "Lofi Girl",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(12300000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("1 month ago"),
|
||||||
|
view_count: Some(98000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
visitor_data: Some("CgttSVVrMVpBMEVfZyjM2eWhBg%3D%3D"),
|
||||||
|
)
|
|
@ -0,0 +1,658 @@
|
||||||
|
---
|
||||||
|
source: src/client/channel_tv.rs
|
||||||
|
expression: map_res.c
|
||||||
|
---
|
||||||
|
ChannelTv(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
avatar: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/0Qu_iyV5XEUmy7MBd46TqRzsMuTED6M5zvunG8W6GjOrRn3pgs-BSTLREWopbkmzQIC66R_FPDs=s72-c-k-c0x00ffffff-no-rj",
|
||||||
|
width: 72,
|
||||||
|
height: 72,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
tv_banner: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/PXxQnCyAMLb1SKCBLAMt7Y9EkYe_oCPlVDeNnNcecWC6CdWSvC-czHiNLS_te1DgO4G9qLcQKQ=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/PXxQnCyAMLb1SKCBLAMt7Y9EkYe_oCPlVDeNnNcecWC6CdWSvC-czHiNLS_te1DgO4G9qLcQKQ=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 854,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/PXxQnCyAMLb1SKCBLAMt7Y9EkYe_oCPlVDeNnNcecWC6CdWSvC-czHiNLS_te1DgO4G9qLcQKQ=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/PXxQnCyAMLb1SKCBLAMt7Y9EkYe_oCPlVDeNnNcecWC6CdWSvC-czHiNLS_te1DgO4G9qLcQKQ=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/PXxQnCyAMLb1SKCBLAMt7Y9EkYe_oCPlVDeNnNcecWC6CdWSvC-czHiNLS_te1DgO4G9qLcQKQ=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 2120,
|
||||||
|
height: 1192,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
videos: [
|
||||||
|
VideoItem(
|
||||||
|
id: "p9FfS9l2NVA",
|
||||||
|
name: "🔴LIVE! PANCAKE ART STREAM WITH POKI, JANET, ABE, WENDY, MIYOUNG!",
|
||||||
|
length: None,
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/p9FfS9l2NVA/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/p9FfS9l2NVA/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/p9FfS9l2NVA/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLDJMx8f-8HX5HxX4UoU6seW_D48pw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/p9FfS9l2NVA/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/p9FfS9l2NVA/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/p9FfS9l2NVA/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: Some("2023-04-15T00:00:00Z"),
|
||||||
|
publish_date_txt: Some("Scheduled for 4/15/23, 12:00\u{202f}AM"),
|
||||||
|
view_count: Some(415231200),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: true,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "O6JydZZ4oeg",
|
||||||
|
name: "🔴LIVE! LATE NIGHT VALORANT CUSTOMS WITH FRIENDS",
|
||||||
|
length: Some(21637),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/O6JydZZ4oeg/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/O6JydZZ4oeg/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/O6JydZZ4oeg/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLCIubr_9LF228yHYZ8qNbsansQCsg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/O6JydZZ4oeg/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/O6JydZZ4oeg/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/O6JydZZ4oeg/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("Streamed 19 hours ago"),
|
||||||
|
view_count: Some(154000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "Icncr_uD9uI",
|
||||||
|
name: "Valkyrae finds the Philippines playing GeoGuessr",
|
||||||
|
length: Some(40),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Icncr_uD9uI/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARhLIEUoZTAP&rs=AOn4CLCKbMp0kLZ5PcherysRHhSojpNxXw",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Icncr_uD9uI/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGEsgRShlMA8=&rs=AOn4CLBgiSwjm7nbD3Z76apbfXEAOm4ZRA",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Icncr_uD9uI/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYSyBFKGUwDw==&rs=AOn4CLB_16Ojqn-iGBwWJBOPqgCKSutAOg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Icncr_uD9uI/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGEsgRShlMA8=&rs=AOn4CLA112dBnQCeaPHeV1bogHBbUwxIvw",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Icncr_uD9uI/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGEsgRShlMA8=&rs=AOn4CLD1TkrCpNRnj6BZV7qSIIQCApDA3g",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Icncr_uD9uI/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGEsgRShlMA8=&rs=AOn4CLCcBVkBlipt-vIs5fvg82SzSzOhCQ",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("1 day ago"),
|
||||||
|
view_count: Some(197000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "0CmGjltsNf0",
|
||||||
|
name: "🔴LIVE! extra extra extra secret minecraft pixelmon stream huehuehuehu",
|
||||||
|
length: Some(15429),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0CmGjltsNf0/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0CmGjltsNf0/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0CmGjltsNf0/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLDIWpYtLAFAM0wnRVCBnMV8kjm2ig",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0CmGjltsNf0/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0CmGjltsNf0/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0CmGjltsNf0/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("Streamed 1 day ago"),
|
||||||
|
view_count: Some(126000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "ZFfRrYf11Ns",
|
||||||
|
name: "what is up guys, it\'s sykkuno here",
|
||||||
|
length: Some(47),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZFfRrYf11Ns/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARhkIGQoZDAP&rs=AOn4CLByFuwEpIgs87JsrJi5E-u3ozAhDg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZFfRrYf11Ns/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLDp_GipatHrrwxQthGWT1euKxKogQ",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZFfRrYf11Ns/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYZCBkKGQwDw==&rs=AOn4CLA08FrVUpZ-gbw6c_Nl0HFgd2E0Nw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZFfRrYf11Ns/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLBeOgCqq-lQiYfpWcKhG9kVqpAhmg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZFfRrYf11Ns/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLD8lwtn-8bBC2hfTrejUxv-4vrfGA",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZFfRrYf11Ns/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLAc_p7D9LB2G6OTSIZ2HQQyARi4Ow",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("1 day ago"),
|
||||||
|
view_count: Some(130000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "ZF0dBucsr_Y",
|
||||||
|
name: "🔴LIVE! SHINY HUNTING EVENT IN MINECRAFT PIXELMON!! Prepping for Tournament this upcoming Tuesday!",
|
||||||
|
length: Some(21033),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZF0dBucsr_Y/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZF0dBucsr_Y/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZF0dBucsr_Y/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLC_gc0i4B-YNXgo8Vy-odV8EDYl3w",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZF0dBucsr_Y/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZF0dBucsr_Y/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/ZF0dBucsr_Y/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("Streamed 2 days ago"),
|
||||||
|
view_count: Some(168000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "0JdncHeIH4Y",
|
||||||
|
name: "Drinking And Mario Party Is A Bad Idea",
|
||||||
|
length: Some(607),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0JdncHeIH4Y/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0JdncHeIH4Y/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0JdncHeIH4Y/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLAkO1rWOWBg-bqGpi2YcOaMHuHhKA",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0JdncHeIH4Y/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0JdncHeIH4Y/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/0JdncHeIH4Y/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("3 days ago"),
|
||||||
|
view_count: Some(169000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "aT3awRbkrmE",
|
||||||
|
name: "🔴LIVE! OTV podcast rescheduled! MINECRAFT PIXELMON grinding for tournament next tuesday",
|
||||||
|
length: Some(16263),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/aT3awRbkrmE/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/aT3awRbkrmE/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/aT3awRbkrmE/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBW7btLvwFJehpcCQG7Pf7NY5GWhg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/aT3awRbkrmE/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/aT3awRbkrmE/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/aT3awRbkrmE/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("Streamed 3 days ago"),
|
||||||
|
view_count: Some(150000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "7MuYYZaeMGY",
|
||||||
|
name: "Pokimane inspired Valkyrae to do this",
|
||||||
|
length: Some(48),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/7MuYYZaeMGY/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARhkIGQoZDAP&rs=AOn4CLAMe4zJbFCXEYEkmlz_IlCt0wVlbA",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/7MuYYZaeMGY/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLDge_3nSYUigeoTZFbj11re2Zm-aw",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/7MuYYZaeMGY/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYZCBkKGQwDw==&rs=AOn4CLAKrzrr6nKbHJ8cLLbC2Q9O0yDl6Q",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/7MuYYZaeMGY/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLB0qpFfF0dCr6RVgm0WTuHn1xp7Yw",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/7MuYYZaeMGY/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLBD4Ocl-3BmD3_gNcl7vomIM9N31A",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/7MuYYZaeMGY/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGGQgZChkMA8=&rs=AOn4CLD6CApz_43WzD77sI5HmHfN67AQfw",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("3 days ago"),
|
||||||
|
view_count: Some(231000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "8YHqas_yqxc",
|
||||||
|
name: "🔴LIVE! super secret MINECRAFT PIXELMON grinding stream for tournament!",
|
||||||
|
length: Some(18741),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/8YHqas_yqxc/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/8YHqas_yqxc/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/8YHqas_yqxc/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLDBF3HreXwgG040aAb1za3-NSzKMA",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/8YHqas_yqxc/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/8YHqas_yqxc/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/8YHqas_yqxc/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("Streamed 4 days ago"),
|
||||||
|
view_count: Some(200000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "l-n15_3LPec",
|
||||||
|
name: "Valkyrae Approved OTV&Friends New Intro",
|
||||||
|
length: Some(42),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/l-n15_3LPec/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgBtgiAAoAPigIMCAAQARhRIEkocjAP&rs=AOn4CLAZh6zhNqic1SRPgbqlmT1AVY0DHQ",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/l-n15_3LPec/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AG2CIACgA-KAgwIABABGFEgSShyMA8=&rs=AOn4CLA64LwLd6rHBugVBvo_nUAR8lxjDg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/l-n15_3LPec/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AbYIgAKAD4oCDAgAEAEYUSBJKHIwDw==&rs=AOn4CLBwBNvszWXxocEnOpmhMRC0vDKD-A",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/l-n15_3LPec/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AG2CIACgA-KAgwIABABGFEgSShyMA8=&rs=AOn4CLBkhkehZX9Ga6S2PE7lSMgMhnUc3Q",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/l-n15_3LPec/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AG2CIACgA-KAgwIABABGFEgSShyMA8=&rs=AOn4CLDa_BOAEKPCy3gq_GPT3TuCLbd69A",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/l-n15_3LPec/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AG2CIACgA-KAgwIABABGFEgSShyMA8=&rs=AOn4CLD5HuEQa9IhweU3gqEMlisLKW59EA",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("4 days ago"),
|
||||||
|
view_count: Some(255000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "lTwneHLpAYo",
|
||||||
|
name: "🔴LIVE! MINECRAFT PIXELMON THEN DRUNK WITH SYKKUNO, FUSLIE AND KKATAMINA",
|
||||||
|
length: Some(28571),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lTwneHLpAYo/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lTwneHLpAYo/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lTwneHLpAYo/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLAEMkeC_HFuyXsJr_RPq8n4t8lc4Q",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lTwneHLpAYo/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lTwneHLpAYo/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/lTwneHLpAYo/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCWxlUwW9BgGISaakjGM37aw",
|
||||||
|
name: "Valkyrae",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(3860000),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("Streamed 5 days ago"),
|
||||||
|
view_count: Some(323000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
visitor_data: Some("Cgthc1JHM2E1QkNxZyjwmeehBg%3D%3D"),
|
||||||
|
)
|
|
@ -0,0 +1,658 @@
|
||||||
|
---
|
||||||
|
source: src/client/channel_tv.rs
|
||||||
|
expression: map_res.c
|
||||||
|
---
|
||||||
|
ChannelTv(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
avatar: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/sv-mI1QXWqBbrQPm4j919deVSt6L2r6HmBHTVS9R5Fu5qALvGABzfV4Vt5bjtXrZzdT7kxbh=s72-c-k-c0x00ffffff-no-rj",
|
||||||
|
width: 72,
|
||||||
|
height: 72,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
tv_banner: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/16E_pmaqBBiJdP2m4NBpcMxAc3QznBGsl-wXq3Ja1zkJ-Nudda3GBCmzLBBBI6ORf2_DKFZD=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/16E_pmaqBBiJdP2m4NBpcMxAc3QznBGsl-wXq3Ja1zkJ-Nudda3GBCmzLBBBI6ORf2_DKFZD=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 854,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/16E_pmaqBBiJdP2m4NBpcMxAc3QznBGsl-wXq3Ja1zkJ-Nudda3GBCmzLBBBI6ORf2_DKFZD=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/16E_pmaqBBiJdP2m4NBpcMxAc3QznBGsl-wXq3Ja1zkJ-Nudda3GBCmzLBBBI6ORf2_DKFZD=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/16E_pmaqBBiJdP2m4NBpcMxAc3QznBGsl-wXq3Ja1zkJ-Nudda3GBCmzLBBBI6ORf2_DKFZD=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj",
|
||||||
|
width: 2120,
|
||||||
|
height: 1192,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
videos: [
|
||||||
|
VideoItem(
|
||||||
|
id: "Qt5O4m1Ec2Q",
|
||||||
|
name: "EGAL WIE WEIT",
|
||||||
|
length: Some(165),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Qt5O4m1Ec2Q/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Qt5O4m1Ec2Q/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Qt5O4m1Ec2Q/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLDtI7c4eE1u8uqxg3Irtmf-MGGmFw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Qt5O4m1Ec2Q/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Qt5O4m1Ec2Q/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Qt5O4m1Ec2Q/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(1400),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "Rm6zRFZ4wwE",
|
||||||
|
name: "SICHER BEI DIR",
|
||||||
|
length: Some(156),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Rm6zRFZ4wwE/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Rm6zRFZ4wwE/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Rm6zRFZ4wwE/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLC5UbJUxU8HBUGchCgv0SetZFTnjQ",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Rm6zRFZ4wwE/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Rm6zRFZ4wwE/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/Rm6zRFZ4wwE/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(1200),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "iY-sFmlzPK0",
|
||||||
|
name: "DURCH RAUM UND ZEIT",
|
||||||
|
length: Some(162),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/iY-sFmlzPK0/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/iY-sFmlzPK0/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/iY-sFmlzPK0/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLCh7tYoG_6xw4VgXyDFuCTNETDYwg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/iY-sFmlzPK0/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/iY-sFmlzPK0/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/iY-sFmlzPK0/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(869),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "JzrIx7s7rgQ",
|
||||||
|
name: "FALLEN",
|
||||||
|
length: Some(182),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/JzrIx7s7rgQ/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/JzrIx7s7rgQ/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/JzrIx7s7rgQ/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBmSyAQ9MDfkaYD9S78Rx750S9L4g",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/JzrIx7s7rgQ/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/JzrIx7s7rgQ/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/JzrIx7s7rgQ/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(1000),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "93u_DBVvmog",
|
||||||
|
name: "AUFHÖREN",
|
||||||
|
length: Some(153),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/93u_DBVvmog/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/93u_DBVvmog/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/93u_DBVvmog/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLD9Uh9HmGJHNbsrFFNLBcGTWOD6qw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/93u_DBVvmog/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/93u_DBVvmog/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/93u_DBVvmog/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(541),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "IQ6TL22BNNc",
|
||||||
|
name: "MUSIK MUSIK",
|
||||||
|
length: Some(170),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/IQ6TL22BNNc/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/IQ6TL22BNNc/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/IQ6TL22BNNc/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLB85WMOGLhtIJFBYjubqDiqb5IfZQ",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/IQ6TL22BNNc/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/IQ6TL22BNNc/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/IQ6TL22BNNc/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(454),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "kxt7rRfep34",
|
||||||
|
name: "VORHANG FÄLLT",
|
||||||
|
length: Some(166),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/kxt7rRfep34/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/kxt7rRfep34/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/kxt7rRfep34/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLA8ayzzU7JuY89xlWx3wqnJkfnOjQ",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/kxt7rRfep34/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/kxt7rRfep34/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/kxt7rRfep34/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(1800),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "YrNOaUFg7y0",
|
||||||
|
name: "VERLIEREN",
|
||||||
|
length: Some(167),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/YrNOaUFg7y0/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/YrNOaUFg7y0/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/YrNOaUFg7y0/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLB_Ph13YVWFj9JGmbHBnBOzcbOA6g",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/YrNOaUFg7y0/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/YrNOaUFg7y0/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/YrNOaUFg7y0/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(325),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "CIxzZw0hp0Y",
|
||||||
|
name: "ALLES HAT SEINE ZEIT",
|
||||||
|
length: Some(172),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/CIxzZw0hp0Y/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/CIxzZw0hp0Y/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/CIxzZw0hp0Y/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLCuyBOgqnDfDxPifi1zPCRDI_0oYg",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/CIxzZw0hp0Y/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/CIxzZw0hp0Y/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/CIxzZw0hp0Y/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(2600),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "nA_1PDF77Ns",
|
||||||
|
name: "DAS BESTE AM TAG",
|
||||||
|
length: Some(168),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nA_1PDF77Ns/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nA_1PDF77Ns/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nA_1PDF77Ns/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLAEz6-L8pw8dzG3bwPnz-6VMmH1Ag",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nA_1PDF77Ns/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nA_1PDF77Ns/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/nA_1PDF77Ns/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(1900),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "qW2ic3FeBjM",
|
||||||
|
name: "ICH LASS DICH ZIEHEN",
|
||||||
|
length: Some(287),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/qW2ic3FeBjM/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/qW2ic3FeBjM/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/qW2ic3FeBjM/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLBUN1-VVbDamdYBr4vm0GsTne998g",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/qW2ic3FeBjM/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/qW2ic3FeBjM/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/qW2ic3FeBjM/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(1300),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
VideoItem(
|
||||||
|
id: "jZ2ticfS1D4",
|
||||||
|
name: "DU KANNST MICH SEHEN",
|
||||||
|
length: Some(200),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/jZ2ticfS1D4/default.jpg",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/jZ2ticfS1D4/mqdefault.jpg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/jZ2ticfS1D4/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLC_sXVGbdwZeNWsr90XZjKFQzZNKw",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/jZ2ticfS1D4/hqdefault.jpg",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/jZ2ticfS1D4/sddefault.jpg",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/jZ2ticfS1D4/maxresdefault.jpg",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UC_vmjW5e1xEHhYjY2a0kK1A",
|
||||||
|
name: "Oonagh - Topic",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(2770),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: None,
|
||||||
|
view_count: Some(1900),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
visitor_data: Some("CgtMal9oOXFScTd4cyiXvuWhBg%3D%3D"),
|
||||||
|
)
|
|
@ -0,0 +1,71 @@
|
||||||
|
---
|
||||||
|
source: src/client/channel_tv.rs
|
||||||
|
expression: map_res.c
|
||||||
|
---
|
||||||
|
ChannelTv(
|
||||||
|
id: "UCAkeE1thnToEXZTao-CZkHw",
|
||||||
|
name: "FiveV",
|
||||||
|
subscriber_count: Some(939),
|
||||||
|
avatar: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://yt3.googleusercontent.com/ytc/AGIKgqPN812F8UPxmHD4vUBaoqrjAqzUIWKs7XENz3FO6g=s72-c-k-c0x00ffffff-no-rj",
|
||||||
|
width: 72,
|
||||||
|
height: 72,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
tv_banner: [],
|
||||||
|
videos: [
|
||||||
|
VideoItem(
|
||||||
|
id: "mUOxprz6g1A",
|
||||||
|
name: "👑GoodLifeRP👑 Vorstellungs Video",
|
||||||
|
length: Some(121),
|
||||||
|
thumbnail: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/mUOxprz6g1A/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgB1AaAAuADigIMCAAQARhlIFIoTzAP&rs=AOn4CLDzWpAQemNy4coi5mGX4Zidtz8D6g",
|
||||||
|
width: 120,
|
||||||
|
height: 90,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/mUOxprz6g1A/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLApsX2G48JM12sRKBtz4S4C99LNIg",
|
||||||
|
width: 320,
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/mUOxprz6g1A/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AdQGgALgA4oCDAgAEAEYZSBSKE8wDw==&rs=AOn4CLDi1avXHbcTse7rvzBelOhmZG7_-g",
|
||||||
|
width: 444,
|
||||||
|
height: 250,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/mUOxprz6g1A/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLAeN1JLavadZyIRnBVbsY3q71WmNQ",
|
||||||
|
width: 480,
|
||||||
|
height: 360,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/mUOxprz6g1A/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLDy0YOfnfHhou6_EWPlMMt-k0rMeQ",
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://i.ytimg.com/vi/mUOxprz6g1A/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLBmuGzO6Ti0hVEC1gp0XUA_l6-HNA",
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
channel: Some(ChannelTag(
|
||||||
|
id: "UCAkeE1thnToEXZTao-CZkHw",
|
||||||
|
name: "FiveV",
|
||||||
|
avatar: [],
|
||||||
|
verification: None,
|
||||||
|
subscriber_count: Some(939),
|
||||||
|
)),
|
||||||
|
publish_date: "[date]",
|
||||||
|
publish_date_txt: Some("2 years ago"),
|
||||||
|
view_count: Some(125),
|
||||||
|
is_live: false,
|
||||||
|
is_short: false,
|
||||||
|
is_upcoming: false,
|
||||||
|
short_description: None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
visitor_data: Some("CgtfTVpMVElZSjBVOCj90uWhBg%3D%3D"),
|
||||||
|
)
|
|
@ -764,6 +764,29 @@ pub struct ChannelRss {
|
||||||
pub create_date: OffsetDateTime,
|
pub create_date: OffsetDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// YouTube channel TV feed
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct ChannelTv {
|
||||||
|
/// Unique YouTube Channel-ID (e.g. `UC-lHJZR3Gqxm24_Vd_AJ5Yw`)
|
||||||
|
pub id: String,
|
||||||
|
/// Channel name
|
||||||
|
pub name: String,
|
||||||
|
/// Channel subscriber count
|
||||||
|
///
|
||||||
|
/// [`None`] if the subscriber count was hidden by the owner
|
||||||
|
/// or could not be parsed.
|
||||||
|
pub subscriber_count: Option<u64>,
|
||||||
|
/// Channel avatar / profile picture
|
||||||
|
pub avatar: Vec<Thumbnail>,
|
||||||
|
/// Banner image shown above the channel (16:9 fullscreen format for TV)
|
||||||
|
pub tv_banner: Vec<Thumbnail>,
|
||||||
|
/// List of the latest channel videos
|
||||||
|
pub videos: Vec<VideoItem>,
|
||||||
|
/// YouTube visitor data cookie
|
||||||
|
pub visitor_data: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
/// YouTube video fetched from a channel's RSS feed
|
/// YouTube video fetched from a channel's RSS feed
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
|
@ -848,13 +848,13 @@ impl Display for Country {
|
||||||
impl FromStr for Language {
|
impl FromStr for Language {
|
||||||
type Err = serde_json::Error;
|
type Err = serde_json::Error;
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
serde_json::from_str(&format!("\"{s}\""))
|
serde_json::from_str(&format!("\"{}\"", s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Country {
|
impl FromStr for Country {
|
||||||
type Err = serde_json::Error;
|
type Err = serde_json::Error;
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
serde_json::from_str(&format!("\"{s}\""))
|
serde_json::from_str(&format!("\"{}\"", s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
125
src/timeago.rs
125
src/timeago.rs
|
@ -18,7 +18,7 @@
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use time::{Date, Duration, OffsetDateTime};
|
use time::{Date, Duration, OffsetDateTime, PrimitiveDateTime, Time};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
param::Language,
|
param::Language,
|
||||||
|
@ -76,9 +76,20 @@ pub(crate) struct TaToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum DateCmp {
|
pub(crate) enum DateCmp {
|
||||||
|
// Year
|
||||||
Y,
|
Y,
|
||||||
|
// Month
|
||||||
M,
|
M,
|
||||||
|
// Day
|
||||||
D,
|
D,
|
||||||
|
// Hour in 24hr format
|
||||||
|
Hr,
|
||||||
|
// Hour in 12hr format
|
||||||
|
Hr12,
|
||||||
|
// Minute
|
||||||
|
Mi,
|
||||||
|
// Year in 2-digit format
|
||||||
|
YShort,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<u8> for TimeAgo {
|
impl Mul<u8> for TimeAgo {
|
||||||
|
@ -226,7 +237,7 @@ pub(crate) fn parse_timeago_dt_or_warn(
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a textual date (e.g. "29 minutes ago" or "Jul 2, 2014") into a ParsedDate object.
|
/// Parse a textual date (e.g. "29 minutes ago" or "Jul 2, 2014") into a [`ParsedDate`] object.
|
||||||
///
|
///
|
||||||
/// Returns None if the date could not be parsed.
|
/// Returns None if the date could not be parsed.
|
||||||
pub fn parse_textual_date(lang: Language, textual_date: &str) -> Option<ParsedDate> {
|
pub fn parse_textual_date(lang: Language, textual_date: &str) -> Option<ParsedDate> {
|
||||||
|
@ -254,6 +265,7 @@ pub fn parse_textual_date(lang: Language, textual_date: &str) -> Option<ParsedDa
|
||||||
DateCmp::Y => y = Some(*n),
|
DateCmp::Y => y = Some(*n),
|
||||||
DateCmp::M => m = Some(*n),
|
DateCmp::M => m = Some(*n),
|
||||||
DateCmp::D => d = Some(*n),
|
DateCmp::D => d = Some(*n),
|
||||||
|
_ => {}
|
||||||
});
|
});
|
||||||
|
|
||||||
if m.is_none() {
|
if m.is_none() {
|
||||||
|
@ -274,7 +286,68 @@ pub fn parse_textual_date(lang: Language, textual_date: &str) -> Option<ParsedDa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a textual date (e.g. "29 minutes ago" or "Jul 2, 2014") into a Chrono DateTime object.
|
/// Parse a textual datetime (e.g. "4/14/23, 3:00 PM") into a [`OffsetDateTime`]
|
||||||
|
/// (assuming UTC timezone)
|
||||||
|
pub fn parse_datetime(lang: Language, datetime_txt: &str) -> Option<OffsetDateTime> {
|
||||||
|
let entry = dictionary::entry(lang);
|
||||||
|
let (nums, last_i) = util::parse_numeric_vec_i::<u16>(datetime_txt);
|
||||||
|
|
||||||
|
if nums.len() == entry.datetime_order.len() {
|
||||||
|
let mut y: Option<u16> = None;
|
||||||
|
let mut m: Option<u16> = None;
|
||||||
|
let mut d: Option<u16> = None;
|
||||||
|
let mut hr: Option<u16> = None;
|
||||||
|
let mut mi: Option<u16> = None;
|
||||||
|
|
||||||
|
nums.iter()
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(i, n)| match entry.datetime_order[i] {
|
||||||
|
DateCmp::Y => y = Some(*n),
|
||||||
|
DateCmp::YShort => y = year_from_short(*n),
|
||||||
|
DateCmp::M => m = Some(*n),
|
||||||
|
DateCmp::D => d = Some(*n),
|
||||||
|
DateCmp::Hr => hr = Some(*n),
|
||||||
|
DateCmp::Hr12 => {
|
||||||
|
let pm = datetime_txt
|
||||||
|
.chars()
|
||||||
|
.skip(last_i + 1)
|
||||||
|
.any(|c| c == 'p' || c == 'P');
|
||||||
|
hr = Some(if pm {
|
||||||
|
if *n == 12 {
|
||||||
|
*n
|
||||||
|
} else {
|
||||||
|
*n + 12
|
||||||
|
}
|
||||||
|
} else if *n == 12 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
*n
|
||||||
|
});
|
||||||
|
}
|
||||||
|
DateCmp::Mi => mi = Some(*n),
|
||||||
|
});
|
||||||
|
|
||||||
|
match (y, m, d, hr, mi) {
|
||||||
|
(Some(y), Some(m), Some(d), Some(hr), Some(mi)) => Some(
|
||||||
|
PrimitiveDateTime::new(
|
||||||
|
Date::from_calendar_date(
|
||||||
|
y.into(),
|
||||||
|
util::month_from_n(m as u8)?,
|
||||||
|
d.try_into().ok()?,
|
||||||
|
)
|
||||||
|
.ok()?,
|
||||||
|
Time::from_hms(hr.try_into().ok()?, mi.try_into().ok()?, 0).ok()?,
|
||||||
|
)
|
||||||
|
.assume_utc(),
|
||||||
|
),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a textual date (e.g. "29 minutes ago" or "Jul 2, 2014") into a [`OffsetDateTime`] object.
|
||||||
///
|
///
|
||||||
/// Returns None if the date could not be parsed.
|
/// Returns None if the date could not be parsed.
|
||||||
pub fn parse_textual_date_to_dt(lang: Language, textual_date: &str) -> Option<OffsetDateTime> {
|
pub fn parse_textual_date_to_dt(lang: Language, textual_date: &str) -> Option<OffsetDateTime> {
|
||||||
|
@ -293,6 +366,33 @@ pub(crate) fn parse_textual_date_or_warn(
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_datetime_or_warn(
|
||||||
|
lang: Language,
|
||||||
|
datetime_txt: &str,
|
||||||
|
warnings: &mut Vec<String>,
|
||||||
|
) -> Option<OffsetDateTime> {
|
||||||
|
let res = parse_datetime(lang, datetime_txt);
|
||||||
|
if res.is_none() {
|
||||||
|
warnings.push(format!("could not parse textual date `{datetime_txt}`"));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert year from a short 2 digit representation to the actual year
|
||||||
|
fn year_from_short(short_year: u16) -> Option<u16> {
|
||||||
|
if short_year > 99 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut year: u16 = time::OffsetDateTime::now_utc().year().try_into().ok()?;
|
||||||
|
year = year - (year % 100);
|
||||||
|
|
||||||
|
if short_year > 49 && year >= 100 {
|
||||||
|
year -= 100;
|
||||||
|
}
|
||||||
|
Some(year + short_year)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{collections::BTreeMap, fs::File, io::BufReader};
|
use std::{collections::BTreeMap, fs::File, io::BufReader};
|
||||||
|
@ -654,4 +754,23 @@ mod tests {
|
||||||
let now = OffsetDateTime::now_utc();
|
let now = OffsetDateTime::now_utc();
|
||||||
assert_eq!(date.year(), now.year() - 1);
|
assert_eq!(date.year(), now.year() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t_parse_datetime_samples() {
|
||||||
|
let json_path = path!(*TESTFILES / "dict" / "datetime_samples.json");
|
||||||
|
let json_file = File::open(json_path).unwrap();
|
||||||
|
let datetime_samples: BTreeMap<Language, String> =
|
||||||
|
serde_json::from_reader(BufReader::new(json_file)).unwrap();
|
||||||
|
|
||||||
|
datetime_samples.iter().for_each(|(lang, txt)| {
|
||||||
|
let datetime =
|
||||||
|
parse_datetime(*lang, txt).unwrap_or_else(|| panic!("parse error, lang: {lang}"));
|
||||||
|
assert_eq!(datetime.year(), 2023);
|
||||||
|
assert_eq!(datetime.month(), time::Month::April);
|
||||||
|
assert_eq!(datetime.day(), 14);
|
||||||
|
assert_eq!(datetime.hour(), 15);
|
||||||
|
assert_eq!(datetime.minute(), 0);
|
||||||
|
assert_eq!(datetime.second(), 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,20 @@ pub(crate) struct Entry {
|
||||||
/// Identifiers: `Y`(ear), `M`(month), `W`(eek), `D`(ay),
|
/// Identifiers: `Y`(ear), `M`(month), `W`(eek), `D`(ay),
|
||||||
/// `h`(our), `m`(inute), `s`(econd)
|
/// `h`(our), `m`(inute), `s`(econd)
|
||||||
pub timeago_tokens: phf::Map<&'static str, TaToken>,
|
pub timeago_tokens: phf::Map<&'static str, TaToken>,
|
||||||
/// Order in which to parse numeric date components. Formatted as
|
/// Order in which to parse numeric date components.
|
||||||
/// a string of date identifiers (Y, M, D).
|
|
||||||
///
|
///
|
||||||
/// Examples:
|
/// Examples:
|
||||||
///
|
///
|
||||||
/// - 03.01.2020 => `"DMY"`
|
/// - 03.01.2020 => `"DMY"`
|
||||||
/// - Jan 3, 2020 => `"DY"`
|
/// - Jan 3, 2020 => `"DY"`
|
||||||
pub date_order: &'static [DateCmp],
|
pub date_order: &'static [DateCmp],
|
||||||
|
/// Order in which to parse datetimes.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
///
|
||||||
|
/// - 2023-04-14 15:00 => `[Y,M,D,Hr,Mi]`
|
||||||
|
/// - 4/14/23, 3:00 PM => `[M,D,YShort,Hr12,Mi]`
|
||||||
|
pub datetime_order: &'static [DateCmp],
|
||||||
/// Tokens for parsing month names.
|
/// Tokens for parsing month names.
|
||||||
///
|
///
|
||||||
/// Format: Parsed token -> Month number (starting from 1)
|
/// Format: Parsed token -> Month number (starting from 1)
|
||||||
|
@ -76,6 +82,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -160,6 +167,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -257,6 +265,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -320,6 +329,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -384,6 +394,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 8694567506910003252,
|
key: 8694567506910003252,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -480,6 +491,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -565,6 +577,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -627,6 +640,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -719,6 +733,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -804,6 +819,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -890,6 +906,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -959,6 +976,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1043,6 +1061,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1112,6 +1131,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1170,7 +1190,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Language::En | Language::EnGb | Language::EnIn => Entry {
|
Language::En => Entry {
|
||||||
by_char: false,
|
by_char: false,
|
||||||
timeago_tokens: ::phf::Map {
|
timeago_tokens: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
|
@ -1197,6 +1217,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::M, DateCmp::D, DateCmp::YShort, DateCmp::Hr12, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1232,15 +1253,185 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
},
|
},
|
||||||
comma_decimal: false,
|
comma_decimal: false,
|
||||||
number_tokens: ::phf::Map {
|
number_tokens: ::phf::Map {
|
||||||
key: 14108922650502679131,
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("M", 6),
|
||||||
|
("B", 9),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
album_types: ::phf::Map {
|
||||||
|
key: 8694567506910003252,
|
||||||
|
disps: &[
|
||||||
|
(3, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("show", AlbumType::Show),
|
||||||
|
("ep", AlbumType::Ep),
|
||||||
|
("single", AlbumType::Single),
|
||||||
|
("album", AlbumType::Album),
|
||||||
|
("audiobook", AlbumType::Audiobook),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Language::EnGb => Entry {
|
||||||
|
by_char: false,
|
||||||
|
timeago_tokens: ::phf::Map {
|
||||||
|
key: 7485420634051515786,
|
||||||
|
disps: &[
|
||||||
|
(0, 7),
|
||||||
|
(8, 12),
|
||||||
|
(5, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("months", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("month", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("hours", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("days", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("years", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
("week", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("second", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("day", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("minute", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("seconds", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("weeks", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("hour", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("minutes", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("year", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
|
months: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(8, 0),
|
||||||
|
(5, 8),
|
||||||
|
(4, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("nov", 11),
|
||||||
|
("sept", 9),
|
||||||
|
("apr", 4),
|
||||||
|
("dec", 12),
|
||||||
|
("mar", 3),
|
||||||
|
("jun", 6),
|
||||||
|
("sep", 9),
|
||||||
|
("may", 5),
|
||||||
|
("jul", 7),
|
||||||
|
("jan", 1),
|
||||||
|
("oct", 10),
|
||||||
|
("feb", 2),
|
||||||
|
("aug", 8),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
timeago_nd_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("yesterday", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("today", TaToken { n: 0, unit: Some(TimeUnit::Day) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
comma_decimal: false,
|
||||||
|
number_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("M", 6),
|
||||||
|
("B", 9),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
album_types: ::phf::Map {
|
||||||
|
key: 8694567506910003252,
|
||||||
|
disps: &[
|
||||||
|
(3, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("show", AlbumType::Show),
|
||||||
|
("ep", AlbumType::Ep),
|
||||||
|
("single", AlbumType::Single),
|
||||||
|
("album", AlbumType::Album),
|
||||||
|
("audiobook", AlbumType::Audiobook),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Language::EnIn => Entry {
|
||||||
|
by_char: false,
|
||||||
|
timeago_tokens: ::phf::Map {
|
||||||
|
key: 7485420634051515786,
|
||||||
|
disps: &[
|
||||||
|
(0, 7),
|
||||||
|
(8, 12),
|
||||||
|
(5, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("months", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("month", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("hours", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("days", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("years", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
("week", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("second", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("day", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("minute", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("seconds", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("weeks", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("hour", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("minutes", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("year", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
|
months: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(8, 0),
|
||||||
|
(5, 8),
|
||||||
|
(4, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("nov", 11),
|
||||||
|
("sept", 9),
|
||||||
|
("apr", 4),
|
||||||
|
("dec", 12),
|
||||||
|
("mar", 3),
|
||||||
|
("jun", 6),
|
||||||
|
("sep", 9),
|
||||||
|
("may", 5),
|
||||||
|
("jul", 7),
|
||||||
|
("jan", 1),
|
||||||
|
("oct", 10),
|
||||||
|
("feb", 2),
|
||||||
|
("aug", 8),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
timeago_nd_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("yesterday", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("today", TaToken { n: 0, unit: Some(TimeUnit::Day) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
comma_decimal: false,
|
||||||
|
number_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
(1, 0),
|
(1, 0),
|
||||||
],
|
],
|
||||||
entries: &[
|
entries: &[
|
||||||
("lakh", 5),
|
|
||||||
("crore", 7),
|
("crore", 7),
|
||||||
("M", 6),
|
("lakh", 5),
|
||||||
("B", 9),
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
album_types: ::phf::Map {
|
album_types: ::phf::Map {
|
||||||
|
@ -1284,6 +1475,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1341,7 +1533,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Language::EsUs | Language::Es419 => Entry {
|
Language::Es419 => Entry {
|
||||||
by_char: false,
|
by_char: false,
|
||||||
timeago_tokens: ::phf::Map {
|
timeago_tokens: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
|
@ -1368,6 +1560,92 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
|
months: ::phf::Map {
|
||||||
|
key: 15467950696543387533,
|
||||||
|
disps: &[
|
||||||
|
(1, 0),
|
||||||
|
(1, 6),
|
||||||
|
(0, 4),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("jul", 7),
|
||||||
|
("oct", 10),
|
||||||
|
("ene", 1),
|
||||||
|
("may", 5),
|
||||||
|
("sept", 9),
|
||||||
|
("feb", 2),
|
||||||
|
("nov", 11),
|
||||||
|
("dic", 12),
|
||||||
|
("abr", 4),
|
||||||
|
("jun", 6),
|
||||||
|
("ago", 8),
|
||||||
|
("mar", 3),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
timeago_nd_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("ayer", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("hoy", TaToken { n: 0, unit: Some(TimeUnit::Day) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
comma_decimal: false,
|
||||||
|
number_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(1, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("mil", 3),
|
||||||
|
("M", 6),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
album_types: ::phf::Map {
|
||||||
|
key: 15467950696543387533,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("ep", AlbumType::Ep),
|
||||||
|
("audiolibro", AlbumType::Audiobook),
|
||||||
|
("sencillo", AlbumType::Single),
|
||||||
|
("programa", AlbumType::Show),
|
||||||
|
("álbum", AlbumType::Album),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Language::EsUs => Entry {
|
||||||
|
by_char: false,
|
||||||
|
timeago_tokens: ::phf::Map {
|
||||||
|
key: 10121458955350035957,
|
||||||
|
disps: &[
|
||||||
|
(8, 9),
|
||||||
|
(2, 0),
|
||||||
|
(7, 5),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("segundos", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("meses", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("minutos", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("semanas", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("segundo", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("días", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("mes", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("hora", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("años", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
("día", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("semana", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("horas", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("año", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
("minuto", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr12, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1455,6 +1733,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 14108922650502679131,
|
key: 14108922650502679131,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1535,6 +1814,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::YShort, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1610,6 +1890,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1695,6 +1976,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1757,6 +2039,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::M, DateCmp::D, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1814,7 +2097,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Language::Fr | Language::FrCa => Entry {
|
Language::Fr => Entry {
|
||||||
by_char: false,
|
by_char: false,
|
||||||
timeago_tokens: ::phf::Map {
|
timeago_tokens: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
|
@ -1840,6 +2123,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -1877,12 +2161,99 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
number_tokens: ::phf::Map {
|
number_tokens: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("M", 6),
|
||||||
|
("Md", 9),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
album_types: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
(5, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("microalbum", AlbumType::Ep),
|
||||||
|
("album", AlbumType::Album),
|
||||||
|
("livre audio", AlbumType::Audiobook),
|
||||||
|
("émission", AlbumType::Show),
|
||||||
|
("simple", AlbumType::Single),
|
||||||
|
("ep", AlbumType::Ep),
|
||||||
|
("single", AlbumType::Single),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Language::FrCa => Entry {
|
||||||
|
by_char: false,
|
||||||
|
timeago_tokens: ::phf::Map {
|
||||||
|
key: 10121458955350035957,
|
||||||
|
disps: &[
|
||||||
|
(12, 3),
|
||||||
|
(2, 11),
|
||||||
(2, 0),
|
(2, 0),
|
||||||
],
|
],
|
||||||
entries: &[
|
entries: &[
|
||||||
("G", 9),
|
("minute", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("semaine", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("jour", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("mois", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("semaines", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("jours", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("seconde", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("heures", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("secondes", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("minutes", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("an", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
("ans", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
|
("heure", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
|
months: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(9, 0),
|
||||||
|
(7, 6),
|
||||||
|
(1, 5),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("août", 8),
|
||||||
|
("avr.", 4),
|
||||||
|
("juil.", 7),
|
||||||
|
("févr.", 2),
|
||||||
|
("oct.", 10),
|
||||||
|
("déc.", 12),
|
||||||
|
("janv.", 1),
|
||||||
|
("mars", 3),
|
||||||
|
("juin", 6),
|
||||||
|
("juill.", 7),
|
||||||
|
("nov.", 11),
|
||||||
|
("sept.", 9),
|
||||||
|
("mai", 5),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
timeago_nd_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
|
("hier", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("aujourd'hui", TaToken { n: 0, unit: Some(TimeUnit::Day) }),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
comma_decimal: true,
|
||||||
|
number_tokens: ::phf::Map {
|
||||||
|
key: 12913932095322966823,
|
||||||
|
disps: &[
|
||||||
|
(0, 0),
|
||||||
|
],
|
||||||
|
entries: &[
|
||||||
("M", 6),
|
("M", 6),
|
||||||
("Md", 9),
|
("G", 9),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
album_types: ::phf::Map {
|
album_types: ::phf::Map {
|
||||||
|
@ -1929,6 +2300,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2004,6 +2376,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2082,6 +2455,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2174,6 +2548,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2259,6 +2634,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2336,6 +2712,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2413,6 +2790,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 106375038446233661,
|
key: 106375038446233661,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2498,6 +2876,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 8694567506910003252,
|
key: 8694567506910003252,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2583,6 +2962,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2674,6 +3054,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2751,6 +3132,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2812,6 +3194,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2889,6 +3272,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -2967,6 +3351,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3052,6 +3437,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3128,6 +3514,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::YShort, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3189,6 +3576,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 2980949210194914378,
|
key: 2980949210194914378,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3266,6 +3654,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 471159234146692604,
|
key: 471159234146692604,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3361,6 +3750,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3431,6 +3821,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3516,6 +3907,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3579,6 +3971,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3655,6 +4048,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3725,6 +4119,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3803,6 +4198,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3880,6 +4276,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -3961,6 +4358,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::YShort, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4045,6 +4443,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4129,6 +4528,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4205,6 +4605,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::M, DateCmp::D, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4285,6 +4686,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 8694567506910003252,
|
key: 8694567506910003252,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4377,6 +4779,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4462,6 +4865,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4547,6 +4951,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4617,6 +5022,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4708,6 +5114,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4785,6 +5192,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4871,6 +5279,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -4951,6 +5360,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5031,6 +5441,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5119,6 +5530,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5193,6 +5605,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5262,6 +5675,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5340,6 +5754,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5424,6 +5839,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5508,6 +5924,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5585,6 +6002,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5666,6 +6084,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 10121458955350035957,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5758,6 +6177,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5842,6 +6262,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5920,6 +6341,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -5998,6 +6420,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::Hr, DateCmp::Mi, DateCmp::D, DateCmp::M, DateCmp::Y],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -6060,6 +6483,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -6122,6 +6546,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::D, DateCmp::M, DateCmp::Y, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -6183,6 +6608,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
date_order: &[DateCmp::Y, DateCmp::M, DateCmp::D],
|
||||||
|
datetime_order: &[DateCmp::Y, DateCmp::M, DateCmp::D, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 12913932095322966823,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
@ -6252,6 +6678,7 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
datetime_order: &[DateCmp::M, DateCmp::D, DateCmp::YShort, DateCmp::Hr, DateCmp::Mi],
|
||||||
months: ::phf::Map {
|
months: ::phf::Map {
|
||||||
key: 7485420634051515786,
|
key: 7485420634051515786,
|
||||||
disps: &[
|
disps: &[
|
||||||
|
|
|
@ -116,16 +116,27 @@ where
|
||||||
buf.parse()
|
buf.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse all numbers occurring in a string and reurn them as a vec
|
/// Parse all numbers occurring in a string and return them as a vec
|
||||||
pub fn parse_numeric_vec<F>(string: &str) -> Vec<F>
|
pub fn parse_numeric_vec<F>(string: &str) -> Vec<F>
|
||||||
|
where
|
||||||
|
F: FromStr,
|
||||||
|
{
|
||||||
|
parse_numeric_vec_i(string).0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse all numbers occurring in a string and return them as a vec
|
||||||
|
/// together with the index of the last digit
|
||||||
|
pub fn parse_numeric_vec_i<F>(string: &str) -> (Vec<F>, usize)
|
||||||
where
|
where
|
||||||
F: FromStr,
|
F: FromStr,
|
||||||
{
|
{
|
||||||
let mut numbers = vec![];
|
let mut numbers = vec![];
|
||||||
|
let mut last_i = 0;
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
for c in string.chars() {
|
for (i, c) in string.chars().enumerate() {
|
||||||
if c.is_ascii_digit() {
|
if c.is_ascii_digit() {
|
||||||
|
last_i = i;
|
||||||
buf.push(c);
|
buf.push(c);
|
||||||
} else if !buf.is_empty() {
|
} else if !buf.is_empty() {
|
||||||
buf.parse::<F>().map_or((), |n| numbers.push(n));
|
buf.parse::<F>().map_or((), |n| numbers.push(n));
|
||||||
|
@ -136,7 +147,7 @@ where
|
||||||
buf.parse::<F>().map_or((), |n| numbers.push(n));
|
buf.parse::<F>().map_or((), |n| numbers.push(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
numbers
|
(numbers, last_i)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse textual video length (e.g. `0:49`, `2:02` or `1:48:18`)
|
/// Parse textual video length (e.g. `0:49`, `2:02` or `1:48:18`)
|
||||||
|
|
19821
testfiles/channel_tv/base.json
Normal file
19821
testfiles/channel_tv/base.json
Normal file
File diff suppressed because one or more lines are too long
5117
testfiles/channel_tv/live.json
Normal file
5117
testfiles/channel_tv/live.json
Normal file
File diff suppressed because one or more lines are too long
10452
testfiles/channel_tv/live_upcoming.json
Normal file
10452
testfiles/channel_tv/live_upcoming.json
Normal file
File diff suppressed because one or more lines are too long
4182
testfiles/channel_tv/music.json
Normal file
4182
testfiles/channel_tv/music.json
Normal file
File diff suppressed because it is too large
Load diff
556
testfiles/channel_tv/onevideo.json
Normal file
556
testfiles/channel_tv/onevideo.json
Normal file
|
@ -0,0 +1,556 @@
|
||||||
|
{
|
||||||
|
"contents": {
|
||||||
|
"tvBrowseRenderer": {
|
||||||
|
"content": {
|
||||||
|
"tvSurfaceContentRenderer": {
|
||||||
|
"content": {
|
||||||
|
"sectionListRenderer": {
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"shelfRenderer": {
|
||||||
|
"content": {
|
||||||
|
"horizontalListRenderer": {
|
||||||
|
"continuations": [
|
||||||
|
{
|
||||||
|
"nextContinuationData": {
|
||||||
|
"clickTrackingParams": "CAkQybcCIhMI7fKJz9Cp_gIVdvQRCB0mpAoR",
|
||||||
|
"continuation": "4qmFsgKWARIYVUNBa2VFMXRoblRvRVhaVGFvLUNaa0h3GnprZ0VjQ0dZYUdGVkRRV3RsUlRGMGFHNVViMFZZV2xSaGJ5MURXbXRJZDVnQkFlb0RORU5uWkVaYU1EVkZWMnBDUmtsb2QwbGFhRzlaVmxWT1FtRXlWa1pOV0ZKdllteFNkbEpXYUdGV1IwWjJURlZPWVdFd2FETSUzRA%3D%3D"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"tileRenderer": {
|
||||||
|
"contentId": "mUOxprz6g1A",
|
||||||
|
"contentType": "TILE_CONTENT_TYPE_VIDEO",
|
||||||
|
"header": {
|
||||||
|
"tileHeaderRenderer": {
|
||||||
|
"thumbnail": {
|
||||||
|
"thumbnails": [
|
||||||
|
{
|
||||||
|
"height": 90,
|
||||||
|
"url": "https://i.ytimg.com/vi/mUOxprz6g1A/default.jpg?sqp=-oaymwEkCHgQWvKriqkDGvABAfgB1AaAAuADigIMCAAQARhlIFIoTzAP&rs=AOn4CLDzWpAQemNy4coi5mGX4Zidtz8D6g",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 180,
|
||||||
|
"url": "https://i.ytimg.com/vi/mUOxprz6g1A/mqdefault.jpg?sqp=-oaymwEmCMACELQB8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLApsX2G48JM12sRKBtz4S4C99LNIg",
|
||||||
|
"width": 320
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 250,
|
||||||
|
"url": "https://i.ytimg.com/vi/mUOxprz6g1A/hqdefault.jpg?sqp=-oaymwExCLwDEPoBSFryq4qpAyMIARUAAIhCGAHwAQH4AdQGgALgA4oCDAgAEAEYZSBSKE8wDw==&rs=AOn4CLDi1avXHbcTse7rvzBelOhmZG7_-g",
|
||||||
|
"width": 444
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 360,
|
||||||
|
"url": "https://i.ytimg.com/vi/mUOxprz6g1A/hqdefault.jpg?sqp=-oaymwEmCOADEOgC8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLAeN1JLavadZyIRnBVbsY3q71WmNQ",
|
||||||
|
"width": 480
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 480,
|
||||||
|
"url": "https://i.ytimg.com/vi/mUOxprz6g1A/sddefault.jpg?sqp=-oaymwEmCIAFEOAD8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLDy0YOfnfHhou6_EWPlMMt-k0rMeQ",
|
||||||
|
"width": 640
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 1080,
|
||||||
|
"url": "https://i.ytimg.com/vi/mUOxprz6g1A/maxresdefault.jpg?sqp=-oaymwEmCIAKENAF8quKqQMa8AEB-AHUBoAC4AOKAgwIABABGGUgUihPMA8=&rs=AOn4CLBmuGzO6Ti0hVEC1gp0XUA_l6-HNA",
|
||||||
|
"width": 1920
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"thumbnailOverlays": [
|
||||||
|
{
|
||||||
|
"thumbnailOverlayTimeStatusRenderer": {
|
||||||
|
"style": "DEFAULT",
|
||||||
|
"text": {
|
||||||
|
"accessibility": {
|
||||||
|
"accessibilityData": {
|
||||||
|
"label": "2 minutes, 1 second"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"simpleText": "2:01"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"tileMetadataRenderer": {
|
||||||
|
"lines": [
|
||||||
|
{
|
||||||
|
"lineRenderer": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"lineItemRenderer": {
|
||||||
|
"text": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"text": "FiveV"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lineRenderer": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"lineItemRenderer": {
|
||||||
|
"text": {
|
||||||
|
"accessibility": {
|
||||||
|
"accessibilityData": {
|
||||||
|
"label": "125 views"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"simpleText": "125 views"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lineItemRenderer": {
|
||||||
|
"text": {
|
||||||
|
"simpleText": "•"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lineItemRenderer": {
|
||||||
|
"text": {
|
||||||
|
"simpleText": "2 years ago"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": {
|
||||||
|
"simpleText": "👑GoodLifeRP👑 Vorstellungs Video"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"onSelectCommand": {
|
||||||
|
"clickTrackingParams": "CAoQlDUYACITCO3yic_Qqf4CFXb0EQgdJqQKETIKZy1oaWdoLWNydloYVUNBa2VFMXRoblRvRVhaVGFvLUNaa0h3mgEFEPI4GGaqARhVVUFrZUUxdGhuVG9FWFpUYW8tQ1prSHc=",
|
||||||
|
"watchEndpoint": {
|
||||||
|
"loggingContext": {
|
||||||
|
"vssLoggingContext": {
|
||||||
|
"serializedContextData": "GhhVVUFrZUUxdGhuVG9FWFpUYW8tQ1prSHc%3D"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"params": "wAEB",
|
||||||
|
"playlistId": "UUAkeE1thnToEXZTao-CZkHw",
|
||||||
|
"videoId": "mUOxprz6g1A",
|
||||||
|
"watchEndpointSupportedOnesieConfig": {
|
||||||
|
"html5PlaybackOnesieConfig": {
|
||||||
|
"commonConfig": {
|
||||||
|
"url": "https://rr2---sn-h0jeln7l.googlevideo.com/initplayback?source=youtube&oeis=1&c=TVHTML5&oad=3200&ovd=3200&oaad=3200&oavd=3200&ocs=700&oewis=1&oputc=1&ofpcc=1&msp=1&odepv=1&id=9943b1a6bcfa8350&ip=2003%3Ade%3Aaf16%3A1900%3Af521%3A1529%3A4c2d%3Ad13&initcwndbps=1578750&mt=1681483502"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"style": "TILE_STYLE_YTLR_DEFAULT",
|
||||||
|
"trackingParams": "CAoQlDUYACITCO3yic_Qqf4CFXb0EQgdJqQKEUDQhurn67TsoZkBqgEYVVVBa2VFMXRoblRvRVhaVGFvLUNaa0h3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trackingParams": "CAgQxjkiEwjt8onP0Kn-AhV29BEIHSakChE=",
|
||||||
|
"visibleItemCount": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoint": {
|
||||||
|
"browseEndpoint": {
|
||||||
|
"browseId": "UCAkeE1thnToEXZTao-CZkHw",
|
||||||
|
"canonicalBaseUrl": "/@lftvanshii",
|
||||||
|
"params": "EgZ2aWRlb3MYAyAAcADyBgsKCToCCAGiAQIIAQ%3D%3D"
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAcQ3BwYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
},
|
||||||
|
"headerRenderer": {
|
||||||
|
"shelfHeaderRenderer": {
|
||||||
|
"title": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"navigationEndpoint": {
|
||||||
|
"browseEndpoint": {
|
||||||
|
"browseId": "UCAkeE1thnToEXZTao-CZkHw",
|
||||||
|
"canonicalBaseUrl": "/@lftvanshii",
|
||||||
|
"params": "EgZ2aWRlb3MYAyAAcADyBgsKCToCCAGiAQIIAQ%3D%3D"
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAcQ3BwYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
},
|
||||||
|
"text": "Uploads"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"trackingParams": "CAcQ3BwYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shelfRenderer": {
|
||||||
|
"content": {
|
||||||
|
"horizontalListRenderer": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"tileRenderer": {
|
||||||
|
"contentId": "PLKXzgqjDJuvBrmhX5t4TRcqkQImpywAuO",
|
||||||
|
"contentType": "TILE_CONTENT_TYPE_PLAYLIST",
|
||||||
|
"header": {
|
||||||
|
"tileHeaderRenderer": {
|
||||||
|
"thumbnail": {
|
||||||
|
"thumbnails": [
|
||||||
|
{
|
||||||
|
"height": 90,
|
||||||
|
"url": "https://i.ytimg.com/vi/sHL8wXUbfhg/default.jpg",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 180,
|
||||||
|
"url": "https://i.ytimg.com/vi/sHL8wXUbfhg/mqdefault.jpg",
|
||||||
|
"width": 320
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 250,
|
||||||
|
"url": "https://i.ytimg.com/vi/sHL8wXUbfhg/hqdefault.jpg?sqp=-oaymwEXCLwDEPoBSFryq4qpAwkIARUAAIhCGAE=&rs=AOn4CLAvwxqx0LQpi-NKVtVSH9Ty4CoLSw",
|
||||||
|
"width": 444
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height": 360,
|
||||||
|
"url": "https://i.ytimg.com/vi/sHL8wXUbfhg/hqdefault.jpg",
|
||||||
|
"width": 480
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"thumbnailOverlays": [
|
||||||
|
{
|
||||||
|
"thumbnailOverlayTimeStatusRenderer": {
|
||||||
|
"icon": {
|
||||||
|
"iconType": "PLAYLISTS"
|
||||||
|
},
|
||||||
|
"style": "DEFAULT",
|
||||||
|
"text": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"bold": true,
|
||||||
|
"text": "7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " videos"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"tileMetadataRenderer": {
|
||||||
|
"lines": [
|
||||||
|
{
|
||||||
|
"lineRenderer": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"lineItemRenderer": {
|
||||||
|
"text": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"navigationEndpoint": {
|
||||||
|
"browseEndpoint": {
|
||||||
|
"browseId": "UCAkeE1thnToEXZTao-CZkHw"
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAYQljUYACITCO3yic_Qqf4CFXb0EQgdJqQKETIGZy1oaWdo"
|
||||||
|
},
|
||||||
|
"text": "FiveV"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"wrap": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": {
|
||||||
|
"simpleText": "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"onFocusCommand": {
|
||||||
|
"showHintCommand": {
|
||||||
|
"shouldShowHint": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"onSelectCommand": {
|
||||||
|
"browseEndpoint": {
|
||||||
|
"browseId": "VLPLKXzgqjDJuvBrmhX5t4TRcqkQImpywAuO"
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAYQljUYACITCO3yic_Qqf4CFXb0EQgdJqQKETIGZy1oaWdo"
|
||||||
|
},
|
||||||
|
"style": "TILE_STYLE_YTLR_DEFAULT",
|
||||||
|
"trackingParams": "CAYQljUYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trackingParams": "CAUQxjkiEwjt8onP0Kn-AhV29BEIHSakChE=",
|
||||||
|
"visibleItemCount": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"endpoint": {
|
||||||
|
"browseEndpoint": {
|
||||||
|
"browseId": "UCAkeE1thnToEXZTao-CZkHw",
|
||||||
|
"canonicalBaseUrl": "/@lftvanshii",
|
||||||
|
"params": "EglwbGF5bGlzdHMYAyABcADyBgkKB0IAogECCAE%3D"
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAQQ3BwYASITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
},
|
||||||
|
"headerRenderer": {
|
||||||
|
"shelfHeaderRenderer": {
|
||||||
|
"title": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"navigationEndpoint": {
|
||||||
|
"browseEndpoint": {
|
||||||
|
"browseId": "UCAkeE1thnToEXZTao-CZkHw",
|
||||||
|
"canonicalBaseUrl": "/@lftvanshii",
|
||||||
|
"params": "EglwbGF5bGlzdHMYAyABcADyBgkKB0IAogECCAE%3D"
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAQQ3BwYASITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
},
|
||||||
|
"text": "Created playlists"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"trackingParams": "CAQQ3BwYASITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trackingParams": "CAMQui8iEwjt8onP0Kn-AhV29BEIHSakChE="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"tvSurfaceHeaderRenderer": {
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"subscribeButtonRenderer": {
|
||||||
|
"buttonText": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"text": "Subscribe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"channelId": "UCAkeE1thnToEXZTao-CZkHw",
|
||||||
|
"enabled": true,
|
||||||
|
"longSubscriberCountText": {
|
||||||
|
"accessibility": {
|
||||||
|
"accessibilityData": {
|
||||||
|
"label": "939 subscribers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"simpleText": "939 subscribers"
|
||||||
|
},
|
||||||
|
"serviceEndpoints": [
|
||||||
|
{
|
||||||
|
"authDeterminedCommand": {
|
||||||
|
"authenticatedCommand": {
|
||||||
|
"clickTrackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ==",
|
||||||
|
"subscribeEndpoint": {
|
||||||
|
"channelIds": [
|
||||||
|
"UCAkeE1thnToEXZTao-CZkHw"
|
||||||
|
],
|
||||||
|
"params": "EgIIAhgA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unauthenticatedCommand": {
|
||||||
|
"authRequiredCommand": {
|
||||||
|
"identityActionContext": {
|
||||||
|
"eventTrigger": "ACCOUNT_EVENT_TRIGGER_SUBSCRIBE",
|
||||||
|
"nextEndpoint": {
|
||||||
|
"clickTrackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ==",
|
||||||
|
"commandExecutorCommand": {
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"clickTrackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ==",
|
||||||
|
"signalAction": {
|
||||||
|
"signal": "CLOSE_POPUP"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clickTrackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ==",
|
||||||
|
"subscribeEndpoint": {
|
||||||
|
"channelIds": [
|
||||||
|
"UCAkeE1thnToEXZTao-CZkHw"
|
||||||
|
],
|
||||||
|
"params": "EgIIAhgA"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"clickTrackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ=="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"clickTrackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ==",
|
||||||
|
"unsubscribeEndpoint": {
|
||||||
|
"channelIds": [
|
||||||
|
"UCAkeE1thnToEXZTao-CZkHw"
|
||||||
|
],
|
||||||
|
"params": "CgIIAhgA"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shortSubscriberCountText": {
|
||||||
|
"simpleText": "939"
|
||||||
|
},
|
||||||
|
"showPreferences": false,
|
||||||
|
"subscribed": false,
|
||||||
|
"subscribedButtonText": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"text": "Subscribed"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"subscribedEntityKey": "EhhVQ0FrZUUxdGhuVG9FWFpUYW8tQ1prSHcgMygB",
|
||||||
|
"subscriberCountText": {
|
||||||
|
"simpleText": "939"
|
||||||
|
},
|
||||||
|
"subscriberCountWithSubscribeText": {
|
||||||
|
"simpleText": "940"
|
||||||
|
},
|
||||||
|
"trackingParams": "CAIQmysYACITCO3yic_Qqf4CFXb0EQgdJqQKEQ==",
|
||||||
|
"type": "FREE",
|
||||||
|
"unsubscribeButtonText": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"text": "Unsubscribe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unsubscribedButtonText": {
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"text": "Subscribe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"style": "TV_SURFACE_CONTENT_HEADER_STYLE_BANNER",
|
||||||
|
"thumbnail": {
|
||||||
|
"thumbnails": [
|
||||||
|
{
|
||||||
|
"height": 72,
|
||||||
|
"url": "https://yt3.googleusercontent.com/ytc/AGIKgqPN812F8UPxmHD4vUBaoqrjAqzUIWKs7XENz3FO6g=s72-c-k-c0x00ffffff-no-rj",
|
||||||
|
"width": 72
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"simpleText": "FiveV"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"trackingParams": "CAEQ0IwDIhMI7fKJz9Cp_gIVdvQRCB0mpAoR"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"frameworkUpdates": {
|
||||||
|
"entityBatchUpdate": {
|
||||||
|
"mutations": [
|
||||||
|
{
|
||||||
|
"entityKey": "EhhVQ0FrZUUxdGhuVG9FWFpUYW8tQ1prSHcgMygB",
|
||||||
|
"payload": {
|
||||||
|
"subscriptionStateEntity": {
|
||||||
|
"key": "EhhVQ0FrZUUxdGhuVG9FWFpUYW8tQ1prSHcgMygB",
|
||||||
|
"subscribed": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "ENTITY_MUTATION_TYPE_REPLACE"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timestamp": {
|
||||||
|
"nanos": 347759864,
|
||||||
|
"seconds": "1681484157"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responseContext": {
|
||||||
|
"serviceTrackingParams": [
|
||||||
|
{
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"key": "route",
|
||||||
|
"value": "channel.featured"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "is_casual",
|
||||||
|
"value": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "is_owner",
|
||||||
|
"value": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "is_monetization_enabled",
|
||||||
|
"value": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "num_shelves",
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "is_alc_surface",
|
||||||
|
"value": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "browse_id",
|
||||||
|
"value": "UCAkeE1thnToEXZTao-CZkHw"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "browse_id_prefix",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "logged_in",
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "e",
|
||||||
|
"value": "9405988,23804281,23858057,23918597,23943651,23946420,23966208,23983296,23998056,24004644,24007246,24034168,24036948,24077241,24080738,24120819,24135310,24140247,24166867,24169501,24173287,24181174,24186126,24187043,24187377,24201855,24209350,24211178,24219382,24219713,24228638,24236210,24241378,24248955,24255165,24255543,24255545,24255547,24255549,24262346,24268142,24269412,24269413,24288047,24288664,24289856,24290971,24390675,24391539,24404640,24405914,24407191,24407198,24409417,24415864,24415866,24416290,24425061,24429093,24439361,24439483,24440132,24440406,24441788,24445832,24447671,24450367,24451319,24453129,24455284,24455285,24455286,24456681,24458839,24465011,24465095,24466371,24466462,24466833,24468691,24468724,24469651,24471752,24474986,24476489,24477227,24482081,24483503,24484441,24484443,24485239,24485410,24485421,24486580,24488188,24490510,24492688,24492804,24494081,24494981,24494986,24495060,24495839,24495960,24495965,24495988,24497807,24499289,24499304,24499566,24499577,24499792,24510563,24515366,24516017,24516156,24518452,24519079,24519102,24519143,24530042,24530194,24530296,24530948,24531268,24534337,24534339,24536757,24537200,24537812,24539626,24539641,24539646,24539666,24539775,24550520,39323074,39323341,39323343,39323456,39323458,39323495,39323497,39323565,39323567,39323575,39323577,39323582,39323584,39323668,39323670,39323672,39323674,39323679,39323681"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"service": "GFEEDBACK"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"key": "sugexp",
|
||||||
|
"value": "yttlrso_e,ytposo.bo.me=1,ytpsoso.bo.me=1,ytposo.bo.tso.e=1,ytpsoso.bo.ft=1,ytposo.dzp=1,tre.en=0,cfro=1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"service": "SUGGEST"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"visitorData": "CgtfTVpMVElZSjBVOCj90uWhBg%3D%3D"
|
||||||
|
},
|
||||||
|
"trackingParams": "CAAQhGciEwjt8onP0Kn-AhV29BEIHSakChE="
|
||||||
|
}
|
85
testfiles/dict/datetime_samples.json
Normal file
85
testfiles/dict/datetime_samples.json
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
{
|
||||||
|
"af": "Geskeduleer vir 2023-04-14 15:00",
|
||||||
|
"am": "ለ14/04/2023 15:00 የተዘጋጀ",
|
||||||
|
"ar": "سيتم بثّه مباشرةً في 14/4/2023، 15:00",
|
||||||
|
"as": "14-4-2023, 15.00ৰ বাবে সময়সূচী নিৰ্ধাৰণ কৰা হৈছে",
|
||||||
|
"az": "14.04.23, 15:00 üçün planlaşdırılıb",
|
||||||
|
"be": "Запланавана на 14.04.23, 15:00",
|
||||||
|
"bg": "Насрочено за 14.04.23 г., 15:00 ч.",
|
||||||
|
"bn": "14/4/23, 15:00 তারিখে লাইভ হবে",
|
||||||
|
"bs": "Zakazano za 14. 4. 2023. 15:00",
|
||||||
|
"ca": "S'ha programat per al dia 14/4/23 15:00",
|
||||||
|
"cs": "Naplánováno na 14.04.23 15:00",
|
||||||
|
"da": "Planlagt til 14.04.2023 15.00",
|
||||||
|
"de": "Geplant für: 14.04.23, 15:00",
|
||||||
|
"el": "Προγραμματίστηκε για τις 14/4/23, 15:00",
|
||||||
|
"en": "Scheduled for 4/14/23, 3:00 PM",
|
||||||
|
"en-GB": "Scheduled for 14/04/2023, 15:00",
|
||||||
|
"en-IN": "Scheduled for 14/04/23, 15:00",
|
||||||
|
"es": "Programado para el 14/4/23, 15:00",
|
||||||
|
"es-419": "Programado para el 14/4/23, 15:00",
|
||||||
|
"es-US": "Programado para el 14/4/2023, 3:00 p. m.",
|
||||||
|
"et": "Ajastatud avaldamiseks 14.04.23, 15:00",
|
||||||
|
"eu": "Igorpenaren data: 23/4/14, 15:00",
|
||||||
|
"fa": "زمانبندیشده برای 2023/4/14, 15:00",
|
||||||
|
"fi": "Esitetään 14.4.2023 15.00",
|
||||||
|
"fil": "Naka-iskedyul para sa 4/14/23, 15:00",
|
||||||
|
"fr": "Planifié pour le 14/04/2023 15:00",
|
||||||
|
"fr-CA": "Planifié le 2023-04-14 15 h 00",
|
||||||
|
"gl": "Programado para o 14/04/23, 15:00",
|
||||||
|
"gu": "14/4/23 15:00 માટે શેડ્યૂલ કર્યો",
|
||||||
|
"hi": "14/4/23, 15:00 के लिए शेड्यूल किया गया है",
|
||||||
|
"hr": "Zakazano za 14. 04. 2023. 15:00",
|
||||||
|
"hu": "Ekkorra ütemezve: 2023. 04. 14. 15:00",
|
||||||
|
"hy": "Ցուցադրվելու է՝ 14.04.23, 15:00",
|
||||||
|
"id": "Tayang 14/04/23, 15.00",
|
||||||
|
"is": "Á dagskrá 14.4.2023, 15:00",
|
||||||
|
"it": "Programmato per il giorno 14/04/23, 15:00",
|
||||||
|
"iw": "מתוזמן לתאריך 14.4.2023, 15:00",
|
||||||
|
"ja": "2023/04/14 15:00 に公開予定",
|
||||||
|
"ka": "დაგეგმილია 14.04.23, 15:00-ზე",
|
||||||
|
"kk": "14.04.23, 15:00 күні болады",
|
||||||
|
"km": "បានកំណត់ពេលសម្រាប់ 14/4/23, 15:00",
|
||||||
|
"kn": "14/4/23, 15:00 ಕ್ಕೆ ನಿಗದಿಪಡಿಸಲಾಗಿದೆ",
|
||||||
|
"ko": "예정일: 23. 4. 14. 15:00",
|
||||||
|
"ky": "Качан башталат: 14/4/23 15:00",
|
||||||
|
"lo": "ກຳນົດເວລາໄວ້ສຳລັບ 14/4/2023, 15:00 ແລ້ວ",
|
||||||
|
"lt": "Suplanuota rodyti 2023-04-14 15:00",
|
||||||
|
"lv": "Plānotā tiešraide: 14.04.23 15:00",
|
||||||
|
"mk": "Закажано за 14.4.23, во 15:00",
|
||||||
|
"ml": "14/4/23 15:00-ന് ഷെഡ്യൂൾ ചെയ്തു",
|
||||||
|
"mn": "2023.04.14 15:00-д товлосон",
|
||||||
|
"mr": "14/4/23, 15:00 साठी शेड्यूल केलेले",
|
||||||
|
"ms": "Dijadualkan pada 14/04/23, 15:00",
|
||||||
|
"my": "14/4/23 15:00 အတွက် စီစဉ်ထားသည်",
|
||||||
|
"ne": "23/4/14, 15:00 मा लाइभ हुने भनी समयतालिका तय गरिएको छ।",
|
||||||
|
"nl": "Gepland voor 14-04-2023 15:00",
|
||||||
|
"no": "Planlagt publisert 14.04.2023, 15:00",
|
||||||
|
"or": "4/14/23, 15:00 ପାଇଁ ସମୟ ଧାର୍ଯ୍ୟ କରାଯାଇଛି",
|
||||||
|
"pa": "14/4/23, 15:00 ਲਈ ਨਿਯਤ ਕੀਤਾ ਗਿਆ",
|
||||||
|
"pl": "Zaplanowany na 14.04.2023, 15:00",
|
||||||
|
"pt": "Programado para 14/04/2023, 15:00",
|
||||||
|
"pt-PT": "Agendado para 14/04/23, 15:00",
|
||||||
|
"ro": "Programat pentru 14.04.2023, 15:00",
|
||||||
|
"ru": "Планируемая дата публикации: 14.04.2023, 15:00",
|
||||||
|
"si": "2023-04-14, 15.00 සඳහා සැලසුම් කෙරිණි",
|
||||||
|
"sk": "Naplánované na 14. 4. 2023 15:00",
|
||||||
|
"sl": "Načrtovano za 14. 04. 23, 15:00",
|
||||||
|
"sq": "Planifikuar për 14.4.23, 15:00",
|
||||||
|
"sr": "Заказано за 14.4.23. 15:00",
|
||||||
|
"sr-Latn": "Zakazano za 14.4.23. 15:00",
|
||||||
|
"sv": "Har schemalagts till 2023-04-14 15:00",
|
||||||
|
"sw": "Imeratibiwa kuanza 14/04/2023, 15:00",
|
||||||
|
"ta": "வெளியிடத் திட்டமிடப்பட்டுள்ளது: 14/4/23, 15:00",
|
||||||
|
"te": "14-04-23 15:00 తేదీకి షెడ్యూల్ చేయబడింది",
|
||||||
|
"th": "กำหนดเผยแพร่ 14/4/23 15:00",
|
||||||
|
"tr": "14.04.2023 15:00 tarihi için planlandı",
|
||||||
|
"uk": "Заплановано на 14.04.23, 15:00",
|
||||||
|
"ur": "14/4/23، 15:00 کیلئے شیڈول کردہ",
|
||||||
|
"uz": "Rejalashtirilgan: 14/04/23, 15:00",
|
||||||
|
"vi": "Đã lên lịch xuất bản vào 15:00 14/04/2023",
|
||||||
|
"zh-CN": "预定发布时间:2023/4/14 15:00",
|
||||||
|
"zh-HK": "預定發佈時間:14/4/2023 15:00",
|
||||||
|
"zh-TW": "預定發布時間:2023/4/14 下午15:00",
|
||||||
|
"zu": "Kuhlelelwe umhlaka-4/14/23 15:00"
|
||||||
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
"weke": "W"
|
"weke": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
|
@ -69,6 +70,7 @@
|
||||||
"ደቂቃዎች": "m"
|
"ደቂቃዎች": "m"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ማርች": 3,
|
"ማርች": 3,
|
||||||
"ሜይ": 5,
|
"ሜይ": 5,
|
||||||
|
@ -131,6 +133,7 @@
|
||||||
"يومًا": "D"
|
"يومًا": "D"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"اليوم": "0D",
|
"اليوم": "0D",
|
||||||
|
@ -164,6 +167,7 @@
|
||||||
"সপ্তাহ": "W"
|
"সপ্তাহ": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"আজি": "0D",
|
"আজি": "0D",
|
||||||
|
@ -198,6 +202,7 @@
|
||||||
"saniyə": "s"
|
"saniyə": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
"avq": 8,
|
"avq": 8,
|
||||||
|
@ -259,6 +264,7 @@
|
||||||
"хвіліны": "m"
|
"хвіліны": "m"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"вер": 9,
|
"вер": 9,
|
||||||
"жні": 8,
|
"жні": 8,
|
||||||
|
@ -311,6 +317,7 @@
|
||||||
"часа": "h"
|
"часа": "h"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"вчера": "1D",
|
"вчера": "1D",
|
||||||
|
@ -343,6 +350,7 @@
|
||||||
"সেকেন্ড": "s"
|
"সেকেন্ড": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"অক্টোবর,": 10,
|
"অক্টোবর,": 10,
|
||||||
"আগস্ট,": 8,
|
"আগস্ট,": 8,
|
||||||
|
@ -401,6 +409,7 @@
|
||||||
"sekundu": "s"
|
"sekundu": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
"aug": 8,
|
"aug": 8,
|
||||||
|
@ -453,6 +462,7 @@
|
||||||
"setmanes": "W"
|
"setmanes": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"des.": 12,
|
"des.": 12,
|
||||||
"d’abr.": 4,
|
"d’abr.": 4,
|
||||||
|
@ -506,6 +516,7 @@
|
||||||
"týdny": "W"
|
"týdny": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"dnes": "0D",
|
"dnes": "0D",
|
||||||
|
@ -544,6 +555,7 @@
|
||||||
"år": "Y"
|
"år": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
|
@ -595,6 +607,7 @@
|
||||||
"wochen": "W"
|
"wochen": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"gestern": "1D",
|
"gestern": "1D",
|
||||||
|
@ -633,6 +646,7 @@
|
||||||
"ώρες": "h"
|
"ώρες": "h"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"απρ": 4,
|
"απρ": 4,
|
||||||
"αυγ": 8,
|
"αυγ": 8,
|
||||||
|
@ -666,10 +680,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"en": {
|
"en": {
|
||||||
"equivalent": [
|
"equivalent": [],
|
||||||
"en-GB",
|
|
||||||
"en-IN"
|
|
||||||
],
|
|
||||||
"by_char": false,
|
"by_char": false,
|
||||||
"timeago_tokens": {
|
"timeago_tokens": {
|
||||||
"day": "D",
|
"day": "D",
|
||||||
|
@ -688,6 +699,7 @@
|
||||||
"years": "Y"
|
"years": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "MDyhm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
"aug": 8,
|
"aug": 8,
|
||||||
|
@ -710,7 +722,111 @@
|
||||||
"comma_decimal": false,
|
"comma_decimal": false,
|
||||||
"number_tokens": {
|
"number_tokens": {
|
||||||
"B": 9,
|
"B": 9,
|
||||||
"M": 6,
|
"M": 6
|
||||||
|
},
|
||||||
|
"album_types": {
|
||||||
|
"album": "Album",
|
||||||
|
"audiobook": "Audiobook",
|
||||||
|
"ep": "Ep",
|
||||||
|
"show": "Show",
|
||||||
|
"single": "Single"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en-GB": {
|
||||||
|
"equivalent": [],
|
||||||
|
"by_char": false,
|
||||||
|
"timeago_tokens": {
|
||||||
|
"day": "D",
|
||||||
|
"days": "D",
|
||||||
|
"hour": "h",
|
||||||
|
"hours": "h",
|
||||||
|
"minute": "m",
|
||||||
|
"minutes": "m",
|
||||||
|
"month": "M",
|
||||||
|
"months": "M",
|
||||||
|
"second": "s",
|
||||||
|
"seconds": "s",
|
||||||
|
"week": "W",
|
||||||
|
"weeks": "W",
|
||||||
|
"year": "Y",
|
||||||
|
"years": "Y"
|
||||||
|
},
|
||||||
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
|
"months": {
|
||||||
|
"apr": 4,
|
||||||
|
"aug": 8,
|
||||||
|
"dec": 12,
|
||||||
|
"feb": 2,
|
||||||
|
"jan": 1,
|
||||||
|
"jul": 7,
|
||||||
|
"jun": 6,
|
||||||
|
"mar": 3,
|
||||||
|
"may": 5,
|
||||||
|
"nov": 11,
|
||||||
|
"oct": 10,
|
||||||
|
"sep": 9,
|
||||||
|
"sept": 9
|
||||||
|
},
|
||||||
|
"timeago_nd_tokens": {
|
||||||
|
"today": "0D",
|
||||||
|
"yesterday": "1D"
|
||||||
|
},
|
||||||
|
"comma_decimal": false,
|
||||||
|
"number_tokens": {
|
||||||
|
"B": 9,
|
||||||
|
"M": 6
|
||||||
|
},
|
||||||
|
"album_types": {
|
||||||
|
"album": "Album",
|
||||||
|
"audiobook": "Audiobook",
|
||||||
|
"ep": "Ep",
|
||||||
|
"show": "Show",
|
||||||
|
"single": "Single"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en-IN": {
|
||||||
|
"equivalent": [],
|
||||||
|
"by_char": false,
|
||||||
|
"timeago_tokens": {
|
||||||
|
"day": "D",
|
||||||
|
"days": "D",
|
||||||
|
"hour": "h",
|
||||||
|
"hours": "h",
|
||||||
|
"minute": "m",
|
||||||
|
"minutes": "m",
|
||||||
|
"month": "M",
|
||||||
|
"months": "M",
|
||||||
|
"second": "s",
|
||||||
|
"seconds": "s",
|
||||||
|
"week": "W",
|
||||||
|
"weeks": "W",
|
||||||
|
"year": "Y",
|
||||||
|
"years": "Y"
|
||||||
|
},
|
||||||
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
|
"months": {
|
||||||
|
"apr": 4,
|
||||||
|
"aug": 8,
|
||||||
|
"dec": 12,
|
||||||
|
"feb": 2,
|
||||||
|
"jan": 1,
|
||||||
|
"jul": 7,
|
||||||
|
"jun": 6,
|
||||||
|
"mar": 3,
|
||||||
|
"may": 5,
|
||||||
|
"nov": 11,
|
||||||
|
"oct": 10,
|
||||||
|
"sep": 9,
|
||||||
|
"sept": 9
|
||||||
|
},
|
||||||
|
"timeago_nd_tokens": {
|
||||||
|
"today": "0D",
|
||||||
|
"yesterday": "1D"
|
||||||
|
},
|
||||||
|
"comma_decimal": false,
|
||||||
|
"number_tokens": {
|
||||||
"crore": 7,
|
"crore": 7,
|
||||||
"lakh": 5
|
"lakh": 5
|
||||||
},
|
},
|
||||||
|
@ -742,6 +858,7 @@
|
||||||
"semanas": "W"
|
"semanas": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"abr": 4,
|
"abr": 4,
|
||||||
"ago": 8,
|
"ago": 8,
|
||||||
|
@ -773,10 +890,8 @@
|
||||||
"álbum": "Album"
|
"álbum": "Album"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es-US": {
|
"es-419": {
|
||||||
"equivalent": [
|
"equivalent": [],
|
||||||
"es-419"
|
|
||||||
],
|
|
||||||
"by_char": false,
|
"by_char": false,
|
||||||
"timeago_tokens": {
|
"timeago_tokens": {
|
||||||
"año": "Y",
|
"año": "Y",
|
||||||
|
@ -795,6 +910,59 @@
|
||||||
"semanas": "W"
|
"semanas": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
|
"months": {
|
||||||
|
"abr": 4,
|
||||||
|
"ago": 8,
|
||||||
|
"dic": 12,
|
||||||
|
"ene": 1,
|
||||||
|
"feb": 2,
|
||||||
|
"jul": 7,
|
||||||
|
"jun": 6,
|
||||||
|
"mar": 3,
|
||||||
|
"may": 5,
|
||||||
|
"nov": 11,
|
||||||
|
"oct": 10,
|
||||||
|
"sept": 9
|
||||||
|
},
|
||||||
|
"timeago_nd_tokens": {
|
||||||
|
"ayer": "1D",
|
||||||
|
"hoy": "0D"
|
||||||
|
},
|
||||||
|
"comma_decimal": false,
|
||||||
|
"number_tokens": {
|
||||||
|
"M": 6,
|
||||||
|
"mil": 3
|
||||||
|
},
|
||||||
|
"album_types": {
|
||||||
|
"audiolibro": "Audiobook",
|
||||||
|
"ep": "Ep",
|
||||||
|
"programa": "Show",
|
||||||
|
"sencillo": "Single",
|
||||||
|
"álbum": "Album"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"es-US": {
|
||||||
|
"equivalent": [],
|
||||||
|
"by_char": false,
|
||||||
|
"timeago_tokens": {
|
||||||
|
"año": "Y",
|
||||||
|
"años": "Y",
|
||||||
|
"día": "D",
|
||||||
|
"días": "D",
|
||||||
|
"hora": "h",
|
||||||
|
"horas": "h",
|
||||||
|
"mes": "M",
|
||||||
|
"meses": "M",
|
||||||
|
"minuto": "m",
|
||||||
|
"minutos": "m",
|
||||||
|
"segundo": "s",
|
||||||
|
"segundos": "s",
|
||||||
|
"semana": "W",
|
||||||
|
"semanas": "W"
|
||||||
|
},
|
||||||
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYhm",
|
||||||
"months": {
|
"months": {
|
||||||
"abr": 4,
|
"abr": 4,
|
||||||
"ago": 8,
|
"ago": 8,
|
||||||
|
@ -848,6 +1016,7 @@
|
||||||
"tunni": "h"
|
"tunni": "h"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
"aug": 8,
|
"aug": 8,
|
||||||
|
@ -896,6 +1065,7 @@
|
||||||
"urtebete": "Y"
|
"urtebete": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "yMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"abe.": 12,
|
"abe.": 12,
|
||||||
"abu.": 8,
|
"abu.": 8,
|
||||||
|
@ -939,6 +1109,7 @@
|
||||||
"هفته": "W"
|
"هفته": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"آوریل": 4,
|
"آوریل": 4,
|
||||||
"اوت": 8,
|
"اوت": 8,
|
||||||
|
@ -991,6 +1162,7 @@
|
||||||
"vuotta": "Y"
|
"vuotta": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"eilen": "1D",
|
"eilen": "1D",
|
||||||
|
@ -1023,6 +1195,7 @@
|
||||||
"taon": "Y"
|
"taon": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "MDyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"abr": 4,
|
"abr": 4,
|
||||||
"ago": 8,
|
"ago": 8,
|
||||||
|
@ -1055,9 +1228,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr": {
|
"fr": {
|
||||||
"equivalent": [
|
"equivalent": [],
|
||||||
"fr-CA"
|
|
||||||
],
|
|
||||||
"by_char": false,
|
"by_char": false,
|
||||||
"timeago_tokens": {
|
"timeago_tokens": {
|
||||||
"an": "Y",
|
"an": "Y",
|
||||||
|
@ -1075,6 +1246,61 @@
|
||||||
"semaines": "W"
|
"semaines": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
|
"months": {
|
||||||
|
"août": 8,
|
||||||
|
"avr.": 4,
|
||||||
|
"déc.": 12,
|
||||||
|
"févr.": 2,
|
||||||
|
"janv.": 1,
|
||||||
|
"juil.": 7,
|
||||||
|
"juill.": 7,
|
||||||
|
"juin": 6,
|
||||||
|
"mai": 5,
|
||||||
|
"mars": 3,
|
||||||
|
"nov.": 11,
|
||||||
|
"oct.": 10,
|
||||||
|
"sept.": 9
|
||||||
|
},
|
||||||
|
"timeago_nd_tokens": {
|
||||||
|
"aujourd'hui": "0D",
|
||||||
|
"hier": "1D"
|
||||||
|
},
|
||||||
|
"comma_decimal": true,
|
||||||
|
"number_tokens": {
|
||||||
|
"M": 6,
|
||||||
|
"Md": 9
|
||||||
|
},
|
||||||
|
"album_types": {
|
||||||
|
"album": "Album",
|
||||||
|
"ep": "Ep",
|
||||||
|
"livre audio": "Audiobook",
|
||||||
|
"microalbum": "Ep",
|
||||||
|
"simple": "Single",
|
||||||
|
"single": "Single",
|
||||||
|
"émission": "Show"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fr-CA": {
|
||||||
|
"equivalent": [],
|
||||||
|
"by_char": false,
|
||||||
|
"timeago_tokens": {
|
||||||
|
"an": "Y",
|
||||||
|
"ans": "Y",
|
||||||
|
"heure": "h",
|
||||||
|
"heures": "h",
|
||||||
|
"jour": "D",
|
||||||
|
"jours": "D",
|
||||||
|
"minute": "m",
|
||||||
|
"minutes": "m",
|
||||||
|
"mois": "M",
|
||||||
|
"seconde": "s",
|
||||||
|
"secondes": "s",
|
||||||
|
"semaine": "W",
|
||||||
|
"semaines": "W"
|
||||||
|
},
|
||||||
|
"date_order": "DY",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"août": 8,
|
"août": 8,
|
||||||
"avr.": 4,
|
"avr.": 4,
|
||||||
|
@ -1097,8 +1323,7 @@
|
||||||
"comma_decimal": true,
|
"comma_decimal": true,
|
||||||
"number_tokens": {
|
"number_tokens": {
|
||||||
"G": 9,
|
"G": 9,
|
||||||
"M": 6,
|
"M": 6
|
||||||
"Md": 9
|
|
||||||
},
|
},
|
||||||
"album_types": {
|
"album_types": {
|
||||||
"album": "Album",
|
"album": "Album",
|
||||||
|
@ -1130,6 +1355,7 @@
|
||||||
"semanas": "W"
|
"semanas": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"abr.": 4,
|
"abr.": 4,
|
||||||
"ago.": 8,
|
"ago.": 8,
|
||||||
|
@ -1173,6 +1399,7 @@
|
||||||
"સેકંડ": "s"
|
"સેકંડ": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"એપ્રિલ,": 4,
|
"એપ્રિલ,": 4,
|
||||||
"ઑક્ટો,": 10,
|
"ઑક્ટો,": 10,
|
||||||
|
@ -1219,6 +1446,7 @@
|
||||||
"सेकंड": "s"
|
"सेकंड": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"अक्तू॰": 10,
|
"अक्तू॰": 10,
|
||||||
"अग॰": 8,
|
"अग॰": 8,
|
||||||
|
@ -1277,6 +1505,7 @@
|
||||||
"tjedna": "W"
|
"tjedna": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"kol": 8,
|
"kol": 8,
|
||||||
"lip": 6,
|
"lip": 6,
|
||||||
|
@ -1329,6 +1558,7 @@
|
||||||
"órával": "h"
|
"órával": "h"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
"dec.": 12,
|
"dec.": 12,
|
||||||
|
@ -1374,6 +1604,7 @@
|
||||||
"օր": "D"
|
"օր": "D"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ապր,": 4,
|
"ապր,": 4,
|
||||||
"դեկ,": 12,
|
"դեկ,": 12,
|
||||||
|
@ -1419,6 +1650,7 @@
|
||||||
"tahun": "Y"
|
"tahun": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"agu": 8,
|
"agu": 8,
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
|
@ -1471,6 +1703,7 @@
|
||||||
"árum": "Y"
|
"árum": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"des.": 12,
|
"des.": 12,
|
||||||
|
@ -1523,6 +1756,7 @@
|
||||||
"settimane": "W"
|
"settimane": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ago": 8,
|
"ago": 8,
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
|
@ -1580,6 +1814,7 @@
|
||||||
"שתי": "2"
|
"שתי": "2"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"באוג׳": 8,
|
"באוג׳": 8,
|
||||||
"באוק׳": 10,
|
"באוק׳": 10,
|
||||||
|
@ -1625,6 +1860,7 @@
|
||||||
"週": "W"
|
"週": "W"
|
||||||
},
|
},
|
||||||
"date_order": "YMD",
|
"date_order": "YMD",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"日": "1D",
|
"日": "1D",
|
||||||
|
@ -1656,6 +1892,7 @@
|
||||||
"წუთის": "m"
|
"წუთის": "m"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"აგვ.": 8,
|
"აგვ.": 8,
|
||||||
"აპრ.": 4,
|
"აპრ.": 4,
|
||||||
|
@ -1701,6 +1938,7 @@
|
||||||
"секунд": "s"
|
"секунд": "s"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ақп.": 2,
|
"ақп.": 2,
|
||||||
"жел.": 12,
|
"жел.": 12,
|
||||||
|
@ -1747,6 +1985,7 @@
|
||||||
"សប្ដាហ៍មុន": "W"
|
"សប្ដាហ៍មុន": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"កក្កដា": 7,
|
"កក្កដា": 7,
|
||||||
"កញ្ញា": 9,
|
"កញ្ញា": 9,
|
||||||
|
@ -1799,6 +2038,7 @@
|
||||||
"ಸೆಕೆಂಡ್": "s"
|
"ಸೆಕೆಂಡ್": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ಅಕ್ಟೋ": 10,
|
"ಅಕ್ಟೋ": 10,
|
||||||
"ಆಗ": 8,
|
"ಆಗ": 8,
|
||||||
|
@ -1843,6 +2083,7 @@
|
||||||
"초": "s"
|
"초": "s"
|
||||||
},
|
},
|
||||||
"date_order": "YMD",
|
"date_order": "YMD",
|
||||||
|
"datetime_order": "yMDHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"오늘": "0D"
|
"오늘": "0D"
|
||||||
|
@ -1874,6 +2115,7 @@
|
||||||
"секунд": "s"
|
"секунд": "s"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"авг.": 8,
|
"авг.": 8,
|
||||||
"апр.": 4,
|
"апр.": 4,
|
||||||
|
@ -1919,6 +2161,7 @@
|
||||||
"ເດືອນກ່ອນ": "M"
|
"ເດືອນກ່ອນ": "M"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ກ.ຍ.": 9,
|
"ກ.ຍ.": 9,
|
||||||
"ກ.ພ.": 2,
|
"ກ.ພ.": 2,
|
||||||
|
@ -1979,6 +2222,7 @@
|
||||||
"valandų": "h"
|
"valandų": "h"
|
||||||
},
|
},
|
||||||
"date_order": "YMD",
|
"date_order": "YMD",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"vakar": "1D",
|
"vakar": "1D",
|
||||||
|
@ -2018,6 +2262,7 @@
|
||||||
"stundām": "h"
|
"stundām": "h"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
|
@ -2070,6 +2315,7 @@
|
||||||
"часа": "h"
|
"часа": "h"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"вчера": "1D",
|
"вчера": "1D",
|
||||||
|
@ -2103,6 +2349,7 @@
|
||||||
"സെക്കൻഡ്": "s"
|
"സെക്കൻഡ്": "s"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ഏപ്രി": 4,
|
"ഏപ്രി": 4,
|
||||||
"ഒക്ടോ": 10,
|
"ഒക്ടോ": 10,
|
||||||
|
@ -2147,6 +2394,7 @@
|
||||||
"өдрийн": "D"
|
"өдрийн": "D"
|
||||||
},
|
},
|
||||||
"date_order": "YMD",
|
"date_order": "YMD",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"өнөөдөр": "0D",
|
"өнөөдөр": "0D",
|
||||||
|
@ -2186,6 +2434,7 @@
|
||||||
"सेकंदापूर्वी": "s"
|
"सेकंदापूर्वी": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"एप्रि,": 4,
|
"एप्रि,": 4,
|
||||||
"ऑक्टो,": 10,
|
"ऑक्टो,": 10,
|
||||||
|
@ -2232,6 +2481,7 @@
|
||||||
"tahun": "Y"
|
"tahun": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
"dis": 12,
|
"dis": 12,
|
||||||
|
@ -2277,6 +2527,7 @@
|
||||||
"လ": "M"
|
"လ": "M"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"စက်": 9,
|
"စက်": 9,
|
||||||
"ဇန်": 1,
|
"ဇန်": 1,
|
||||||
|
@ -2325,6 +2576,7 @@
|
||||||
"हप्ता": "W"
|
"हप्ता": "W"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "yMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"अक्टोबर": 10,
|
"अक्टोबर": 10,
|
||||||
"अगस्ट": 8,
|
"अगस्ट": 8,
|
||||||
|
@ -2376,6 +2628,7 @@
|
||||||
"weken": "W"
|
"weken": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
|
@ -2427,6 +2680,7 @@
|
||||||
"år": "Y"
|
"år": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
|
@ -2471,6 +2725,7 @@
|
||||||
"ସେକେଣ୍ଡ": "s"
|
"ସେକେଣ୍ଡ": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "MDyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ଅକ୍ଟୋବର": 10,
|
"ଅକ୍ଟୋବର": 10,
|
||||||
"ଅଗଷ୍ଟ": 8,
|
"ଅଗଷ୍ଟ": 8,
|
||||||
|
@ -2519,6 +2774,7 @@
|
||||||
"ਹਫ਼ਤੇ": "W"
|
"ਹਫ਼ਤੇ": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ਅਕਤੂ": 10,
|
"ਅਕਤੂ": 10,
|
||||||
"ਅਗ": 8,
|
"ਅਗ": 8,
|
||||||
|
@ -2577,6 +2833,7 @@
|
||||||
"tygodnie": "W"
|
"tygodnie": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"cze": 6,
|
"cze": 6,
|
||||||
"gru": 12,
|
"gru": 12,
|
||||||
|
@ -2629,6 +2886,7 @@
|
||||||
"semanas": "W"
|
"semanas": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"abr.": 4,
|
"abr.": 4,
|
||||||
"ago.": 8,
|
"ago.": 8,
|
||||||
|
@ -2681,6 +2939,7 @@
|
||||||
"semanas": "W"
|
"semanas": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"hoje": "0D",
|
"hoje": "0D",
|
||||||
|
@ -2720,6 +2979,7 @@
|
||||||
"zile": "D"
|
"zile": "D"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
|
@ -2777,6 +3037,7 @@
|
||||||
"часов": "h"
|
"часов": "h"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"авг.": 8,
|
"авг.": 8,
|
||||||
"апр.": 4,
|
"апр.": 4,
|
||||||
|
@ -2822,6 +3083,7 @@
|
||||||
"සති": "W"
|
"සති": "W"
|
||||||
},
|
},
|
||||||
"date_order": "YD",
|
"date_order": "YD",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"අගෝ": 8,
|
"අගෝ": 8,
|
||||||
"අප්රේල්": 4,
|
"අප්රේල්": 4,
|
||||||
|
@ -2875,6 +3137,7 @@
|
||||||
"týždňom": "W"
|
"týždňom": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"dnes": "0D",
|
"dnes": "0D",
|
||||||
|
@ -2922,6 +3185,7 @@
|
||||||
"uro": "h"
|
"uro": "h"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"avg.": 8,
|
"avg.": 8,
|
||||||
|
@ -2970,6 +3234,7 @@
|
||||||
"vjet": "Y"
|
"vjet": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"dhj": 12,
|
"dhj": 12,
|
||||||
"gush": 8,
|
"gush": 8,
|
||||||
|
@ -3024,6 +3289,7 @@
|
||||||
"секунди": "s"
|
"секунди": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"данас": "0D",
|
"данас": "0D",
|
||||||
|
@ -3066,6 +3332,7 @@
|
||||||
"sekundi": "s"
|
"sekundi": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"danas": "0D",
|
"danas": "0D",
|
||||||
|
@ -3104,6 +3371,7 @@
|
||||||
"år": "Y"
|
"år": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr.": 4,
|
"apr.": 4,
|
||||||
"aug.": 8,
|
"aug.": 8,
|
||||||
|
@ -3150,6 +3418,7 @@
|
||||||
"wiki": "W"
|
"wiki": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ago": 8,
|
"ago": 8,
|
||||||
"apr": 4,
|
"apr": 4,
|
||||||
|
@ -3201,6 +3470,7 @@
|
||||||
"விநாடிக்கு": "s"
|
"விநாடிக்கு": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"அக்.,": 10,
|
"அக்.,": 10,
|
||||||
"ஆக.,": 8,
|
"ஆக.,": 8,
|
||||||
|
@ -3252,6 +3522,7 @@
|
||||||
"సెకన్ల": "s"
|
"సెకన్ల": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"అక్టో,": 10,
|
"అక్టో,": 10,
|
||||||
"ఆగ,": 8,
|
"ఆగ,": 8,
|
||||||
|
@ -3297,6 +3568,7 @@
|
||||||
"เดือนที่ผ่านมา": "M"
|
"เดือนที่ผ่านมา": "M"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ก.ค.": 7,
|
"ก.ค.": 7,
|
||||||
"ก.พ.": 2,
|
"ก.พ.": 2,
|
||||||
|
@ -3345,6 +3617,7 @@
|
||||||
"yıl": "Y"
|
"yıl": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {
|
"months": {
|
||||||
"ara": 12,
|
"ara": 12,
|
||||||
"ağu": 8,
|
"ağu": 8,
|
||||||
|
@ -3403,6 +3676,7 @@
|
||||||
"хвилину": "m"
|
"хвилину": "m"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"бер.": 3,
|
"бер.": 3,
|
||||||
"вер.": 9,
|
"вер.": 9,
|
||||||
|
@ -3454,6 +3728,7 @@
|
||||||
"ہفتے": "W"
|
"ہفتے": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"اپریل،": 4,
|
"اپریل،": 4,
|
||||||
"اکتوبر،": 10,
|
"اکتوبر،": 10,
|
||||||
|
@ -3500,6 +3775,7 @@
|
||||||
"yil": "Y"
|
"yil": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "DMyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"apr,": 4,
|
"apr,": 4,
|
||||||
"avg,": 8,
|
"avg,": 8,
|
||||||
|
@ -3546,6 +3822,7 @@
|
||||||
"tuần": "W"
|
"tuần": "W"
|
||||||
},
|
},
|
||||||
"date_order": "DMY",
|
"date_order": "DMY",
|
||||||
|
"datetime_order": "HmDMY",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"nay": "0D",
|
"nay": "0D",
|
||||||
|
@ -3578,6 +3855,7 @@
|
||||||
"秒": "s"
|
"秒": "s"
|
||||||
},
|
},
|
||||||
"date_order": "YMD",
|
"date_order": "YMD",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"今": "0D",
|
"今": "0D",
|
||||||
|
@ -3610,6 +3888,7 @@
|
||||||
"秒": "s"
|
"秒": "s"
|
||||||
},
|
},
|
||||||
"date_order": "YMD",
|
"date_order": "YMD",
|
||||||
|
"datetime_order": "DMYHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"今": "0D",
|
"今": "0D",
|
||||||
|
@ -3641,6 +3920,7 @@
|
||||||
"週": "W"
|
"週": "W"
|
||||||
},
|
},
|
||||||
"date_order": "YMD",
|
"date_order": "YMD",
|
||||||
|
"datetime_order": "YMDHm",
|
||||||
"months": {},
|
"months": {},
|
||||||
"timeago_nd_tokens": {
|
"timeago_nd_tokens": {
|
||||||
"今": "0D",
|
"今": "0D",
|
||||||
|
@ -3679,6 +3959,7 @@
|
||||||
"unyaka": "Y"
|
"unyaka": "Y"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
|
"datetime_order": "MDyHm",
|
||||||
"months": {
|
"months": {
|
||||||
"aga": 8,
|
"aga": 8,
|
||||||
"dis": 12,
|
"dis": 12,
|
||||||
|
|
|
@ -1023,6 +1023,30 @@ mod channel_rss {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//# CHANNEL TV
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case::default("UCHnyfMqiRRG1u-2MsSQLbXA", "Veritasium", 13_000_000, false)]
|
||||||
|
#[case::empty("UCApUH1k001sYlUTIIVIqGCA", "FreeUser", 600, true)]
|
||||||
|
#[case::music("UC_vmjW5e1xEHhYjY2a0kK1A", "Oonagh - Topic", 2000, true)]
|
||||||
|
fn get_channel_tv(
|
||||||
|
#[case] id: &str,
|
||||||
|
#[case] name: &str,
|
||||||
|
#[case] subscribers: u64,
|
||||||
|
#[case] empty: bool,
|
||||||
|
rp: RustyPipe,
|
||||||
|
) {
|
||||||
|
let channel = tokio_test::block_on(rp.query().channel_tv(id)).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(channel.id, id);
|
||||||
|
assert_eq!(channel.name, name);
|
||||||
|
assert!(channel.subscriber_count.unwrap() > subscribers);
|
||||||
|
assert!(!channel.tv_banner.is_empty(), "got no tv banners");
|
||||||
|
if !empty {
|
||||||
|
assert!(!channel.videos.is_empty(), "got no videos");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//#SEARCH
|
//#SEARCH
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
|
Loading…
Reference in a new issue