fix: A/B test 21: music album recommendations
This commit is contained in:
parent
544782f8de
commit
6737512f5f
13 changed files with 8680 additions and 113 deletions
|
|
@ -40,13 +40,11 @@ pub enum ABTest {
|
|||
MusicPlaylistFacepile = 18,
|
||||
MusicAlbumGroupsReordered = 19,
|
||||
MusicContinuationItemRenderer = 20,
|
||||
AlbumRecommends = 21,
|
||||
}
|
||||
|
||||
/// List of active A/B tests that are run when none is manually specified
|
||||
const TESTS_TO_RUN: &[ABTest] = &[
|
||||
ABTest::MusicAlbumGroupsReordered,
|
||||
ABTest::MusicContinuationItemRenderer,
|
||||
];
|
||||
const TESTS_TO_RUN: &[ABTest] = &[ABTest::MusicAlbumGroupsReordered, ABTest::AlbumRecommends];
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ABTestRes {
|
||||
|
|
@ -121,6 +119,7 @@ pub async fn run_test(
|
|||
ABTest::MusicContinuationItemRenderer => {
|
||||
music_continuation_item_renderer(&query).await
|
||||
}
|
||||
ABTest::AlbumRecommends => album_recommends(&query).await,
|
||||
}
|
||||
.unwrap();
|
||||
pb.inc(1);
|
||||
|
|
@ -443,3 +442,18 @@ pub async fn music_continuation_item_renderer(rp: &RustyPipeQuery) -> Result<boo
|
|||
.await?;
|
||||
Ok(res.contains("\"continuationItemRenderer\""))
|
||||
}
|
||||
|
||||
pub async fn album_recommends(rp: &RustyPipeQuery) -> Result<bool> {
|
||||
let id = "MPREb_u1I69lSAe5v";
|
||||
let res = rp
|
||||
.raw(
|
||||
ClientType::DesktopMusic,
|
||||
"browse",
|
||||
&QBrowse {
|
||||
browse_id: id,
|
||||
params: None,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
Ok(res.contains("\"musicCarouselShelfRenderer\""))
|
||||
}
|
||||
|
|
|
|||
130
codegen/src/collect_album_versions_titles.rs
Normal file
130
codegen/src/collect_album_versions_titles.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
use std::{collections::BTreeMap, fs::File, io::BufReader};
|
||||
|
||||
use path_macro::path;
|
||||
use rustypipe::{
|
||||
client::{ClientType, RustyPipe},
|
||||
param::{Language, LANGUAGES},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_with::rust::deserialize_ignore_any;
|
||||
|
||||
use crate::{
|
||||
model::{QBrowse, SectionList, TextRuns},
|
||||
util::{self, DICT_DIR},
|
||||
};
|
||||
|
||||
pub async fn collect_album_versions_titles() {
|
||||
let json_path = path!(*DICT_DIR / "other_versions_titles.json");
|
||||
let mut res = BTreeMap::new();
|
||||
|
||||
let rp = RustyPipe::new();
|
||||
|
||||
for lang in LANGUAGES {
|
||||
let query = QBrowse {
|
||||
browse_id: "MPREb_nlBWQROfvjo",
|
||||
params: None,
|
||||
};
|
||||
let raw_resp = rp
|
||||
.query()
|
||||
.lang(lang)
|
||||
.raw(ClientType::DesktopMusic, "browse", &query)
|
||||
.await
|
||||
.unwrap();
|
||||
let data = serde_json::from_str::<AlbumData>(&raw_resp).unwrap();
|
||||
let title = data
|
||||
.contents
|
||||
.two_column_browse_results_renderer
|
||||
.secondary_contents
|
||||
.section_list_renderer
|
||||
.contents
|
||||
.into_iter()
|
||||
.find_map(|x| match x {
|
||||
ItemSection::MusicCarouselShelfRenderer(music_carousel_shelf) => {
|
||||
Some(music_carousel_shelf)
|
||||
}
|
||||
ItemSection::None => None,
|
||||
})
|
||||
.expect("other versions")
|
||||
.header
|
||||
.expect("header")
|
||||
.music_carousel_shelf_basic_header_renderer
|
||||
.title
|
||||
.runs
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap()
|
||||
.text;
|
||||
println!("{lang}: {title}");
|
||||
res.insert(lang, title);
|
||||
}
|
||||
|
||||
let file = File::create(json_path).unwrap();
|
||||
serde_json::to_writer_pretty(file, &res).unwrap();
|
||||
}
|
||||
|
||||
pub fn write_samples_to_dict() {
|
||||
let json_path = path!(*DICT_DIR / "other_versions_titles.json");
|
||||
let json_file = File::open(json_path).unwrap();
|
||||
let collected: BTreeMap<Language, String> =
|
||||
serde_json::from_reader(BufReader::new(json_file)).unwrap();
|
||||
let mut dict = util::read_dict();
|
||||
let langs = dict.keys().copied().collect::<Vec<_>>();
|
||||
|
||||
for lang in langs {
|
||||
let dict_entry = dict.entry(lang).or_default();
|
||||
|
||||
let e = collected.get(&lang).unwrap();
|
||||
assert_eq!(e, e.trim());
|
||||
dict_entry.album_versions_title = e.to_owned();
|
||||
|
||||
for lang in &dict_entry.equivalent {
|
||||
let ee = collected.get(lang).unwrap();
|
||||
if ee != e {
|
||||
panic!("equivalent lang conflict, lang: {lang}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
util::write_dict(dict);
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct AlbumData {
|
||||
contents: AlbumDataContents,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct AlbumDataContents {
|
||||
two_column_browse_results_renderer: X1,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct X1 {
|
||||
secondary_contents: SectionList<ItemSection>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
enum ItemSection {
|
||||
MusicCarouselShelfRenderer(MusicCarouselShelf),
|
||||
#[serde(other, deserialize_with = "deserialize_ignore_any")]
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct MusicCarouselShelf {
|
||||
header: Option<MusicCarouselShelfHeader>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct MusicCarouselShelfHeader {
|
||||
music_carousel_shelf_basic_header_renderer: MusicCarouselShelfHeaderRenderer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct MusicCarouselShelfHeaderRenderer {
|
||||
title: TextRuns,
|
||||
}
|
||||
|
|
@ -90,6 +90,8 @@ pub(crate) struct Entry {
|
|||
pub chan_prefix: &'static str,
|
||||
/// Channel name suffix on playlist pages
|
||||
pub chan_suffix: &'static str,
|
||||
/// "Other versions" title on album pages
|
||||
pub album_versions_title: &'static str,
|
||||
}
|
||||
"#;
|
||||
|
||||
|
|
@ -178,8 +180,8 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
|||
.to_string()
|
||||
.replace('\n', "\n ");
|
||||
|
||||
write!(code_timeago_tokens, "{} => Entry {{\n timeago_tokens: {},\n month_before_day: {:?},\n months: {},\n timeago_nd_tokens: {},\n comma_decimal: {:?},\n number_tokens: {},\n number_nd_tokens: {},\n album_types: {},\n chan_prefix: {:?},\n chan_suffix: {:?},\n }},\n ",
|
||||
selector, code_ta_tokens, entry.month_before_day, code_months, code_ta_nd_tokens, entry.comma_decimal, code_number_tokens, code_number_nd_tokens, code_album_types, entry.chan_prefix, entry.chan_suffix).unwrap();
|
||||
write!(code_timeago_tokens, "{} => Entry {{\n timeago_tokens: {},\n month_before_day: {:?},\n months: {},\n timeago_nd_tokens: {},\n comma_decimal: {:?},\n number_tokens: {},\n number_nd_tokens: {},\n album_types: {},\n chan_prefix: {:?},\n chan_suffix: {:?},\n album_versions_title: {:?},\n }},\n ",
|
||||
selector, code_ta_tokens, entry.month_before_day, code_months, code_ta_nd_tokens, entry.comma_decimal, code_number_tokens, code_number_nd_tokens, code_album_types, entry.chan_prefix, entry.chan_suffix, entry.album_versions_title).unwrap();
|
||||
}
|
||||
|
||||
code_timeago_tokens = code_timeago_tokens.trim_end().to_owned() + "\n }\n}\n";
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
mod abtest;
|
||||
mod collect_album_types;
|
||||
mod collect_album_versions_titles;
|
||||
mod collect_chan_prefixes;
|
||||
mod collect_history_dates;
|
||||
mod collect_large_numbers;
|
||||
|
|
@ -34,12 +35,14 @@ enum Commands {
|
|||
CollectHistoryDates,
|
||||
CollectMusicHistoryDates,
|
||||
CollectChanPrefixes,
|
||||
CollectAlbumVersionsTitles,
|
||||
ParsePlaylistDates,
|
||||
ParseHistoryDates,
|
||||
ParseLargeNumbers,
|
||||
ParseAlbumTypes,
|
||||
ParseVideoDurations,
|
||||
ParseChanPrefixes,
|
||||
ParseAlbumVersionsTitles,
|
||||
GenLocales,
|
||||
GenDict,
|
||||
DownloadTestfiles,
|
||||
|
|
@ -58,28 +61,25 @@ async fn main() {
|
|||
|
||||
match cli.command {
|
||||
Commands::CollectPlaylistDates => {
|
||||
collect_playlist_dates::collect_dates(cli.concurrency).await;
|
||||
collect_playlist_dates::collect_dates(cli.concurrency).await
|
||||
}
|
||||
Commands::CollectLargeNumbers => {
|
||||
collect_large_numbers::collect_large_numbers(cli.concurrency).await;
|
||||
collect_large_numbers::collect_large_numbers(cli.concurrency).await
|
||||
}
|
||||
Commands::CollectAlbumTypes => {
|
||||
collect_album_types::collect_album_types(cli.concurrency).await;
|
||||
collect_album_types::collect_album_types(cli.concurrency).await
|
||||
}
|
||||
Commands::CollectVideoDurations => {
|
||||
collect_video_durations::collect_video_durations(cli.concurrency).await;
|
||||
collect_video_durations::collect_video_durations(cli.concurrency).await
|
||||
}
|
||||
Commands::CollectVideoDates => {
|
||||
collect_video_dates::collect_video_dates(cli.concurrency).await;
|
||||
collect_video_dates::collect_video_dates(cli.concurrency).await
|
||||
}
|
||||
Commands::CollectHistoryDates => {
|
||||
collect_history_dates::collect_dates().await;
|
||||
}
|
||||
Commands::CollectMusicHistoryDates => {
|
||||
collect_history_dates::collect_dates_music().await;
|
||||
}
|
||||
Commands::CollectChanPrefixes => {
|
||||
collect_chan_prefixes::collect_chan_prefixes().await;
|
||||
Commands::CollectHistoryDates => collect_history_dates::collect_dates().await,
|
||||
Commands::CollectMusicHistoryDates => collect_history_dates::collect_dates_music().await,
|
||||
Commands::CollectChanPrefixes => collect_chan_prefixes::collect_chan_prefixes().await,
|
||||
Commands::CollectAlbumVersionsTitles => {
|
||||
collect_album_versions_titles::collect_album_versions_titles().await
|
||||
}
|
||||
Commands::ParsePlaylistDates => collect_playlist_dates::write_samples_to_dict(),
|
||||
Commands::ParseHistoryDates => collect_history_dates::write_samples_to_dict(),
|
||||
|
|
@ -87,9 +87,10 @@ async fn main() {
|
|||
Commands::ParseAlbumTypes => collect_album_types::write_samples_to_dict(),
|
||||
Commands::ParseVideoDurations => collect_video_durations::parse_video_durations(),
|
||||
Commands::ParseChanPrefixes => collect_chan_prefixes::write_samples_to_dict(),
|
||||
Commands::GenLocales => {
|
||||
gen_locales::generate_locales().await;
|
||||
Commands::ParseAlbumVersionsTitles => {
|
||||
collect_album_versions_titles::write_samples_to_dict()
|
||||
}
|
||||
Commands::GenLocales => gen_locales::generate_locales().await,
|
||||
Commands::GenDict => gen_dictionary::generate_dictionary(),
|
||||
Commands::DownloadTestfiles => download_testfiles::download_testfiles().await,
|
||||
Commands::AbTest { id, n } => {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ pub struct DictEntry {
|
|||
pub chan_prefix: String,
|
||||
/// Channel name suffix on playlist pages
|
||||
pub chan_suffix: String,
|
||||
/// "Other versions" title on album pages
|
||||
pub album_versions_title: String,
|
||||
}
|
||||
|
||||
/// Parsed TimeAgo string, contains amount and time unit.
|
||||
|
|
|
|||
Reference in a new issue