From 53d2ddd272499b2dfe2c49a9d386d9d23533ac22 Mon Sep 17 00:00:00 2001 From: SamTV12345 <40429738+SamTV12345@users.noreply.github.com> Date: Fri, 24 Nov 2023 22:00:07 +0100 Subject: [PATCH] Added migration for converting to new podcast watchlog format. (#454) * Added migration for converting to new podcast watchlog format. * Fixed clippy. --- src/command_line_runner.rs | 13 ++++-- src/constants/inner_constants.rs | 3 ++ src/dbconfig/mod.rs | 10 +++++ src/models/podcast_history_item.rs | 69 +++++++++++++++++++++++++++--- src/models/subscription.rs | 3 +- 5 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/command_line_runner.rs b/src/command_line_runner.rs index e289fa07..f765a2ac 100644 --- a/src/command_line_runner.rs +++ b/src/command_line_runner.rs @@ -217,12 +217,19 @@ pub fn start_command_line(mut args: Args) { } } } - "migration" => { - if args.next().unwrap().as_str() == "episodes" { + "migration" => match args.next().unwrap().as_str() { + "episodes" => { Episode::migrate_episode_urls(&mut establish_connection()); println!("Successfully migrated episode urls.") } - } + "watchlog" => { + PodcastHistoryItem::migrate_watchlog(&mut establish_connection()); + println!("Successfully migrated history into episodes.") + } + _ => { + error!("Command not found") + } + }, "debug" => { create_debug_message(); } diff --git a/src/constants/inner_constants.rs b/src/constants/inner_constants.rs index d75ab8cf..eecc32ea 100644 --- a/src/constants/inner_constants.rs +++ b/src/constants/inner_constants.rs @@ -128,3 +128,6 @@ pub const COMMON_USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) A (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"; pub const OIDC_JWKS: &str = "OIDC_JWKS"; + +// Default device when viewing via web interface +pub const DEFAULT_DEVICE: &str = "webview"; diff --git a/src/dbconfig/mod.rs b/src/dbconfig/mod.rs index e129b43e..c90b5773 100644 --- a/src/dbconfig/mod.rs +++ b/src/dbconfig/mod.rs @@ -26,3 +26,13 @@ macro_rules! execute_with_conn { } }; } + +#[macro_export] +macro_rules! insert_with_conn { + ($conn:expr, $diesel_func:expr) => { + match $conn { + DbConnection::Sqlite(conn) => $diesel_func(conn), + DbConnection::Postgresql(conn) => $diesel_func(conn), + } + }; +} diff --git a/src/models/podcast_history_item.rs b/src/models/podcast_history_item.rs index 40c556da..edc0918d 100644 --- a/src/models/podcast_history_item.rs +++ b/src/models/podcast_history_item.rs @@ -1,4 +1,7 @@ -use crate::constants::inner_constants::STANDARD_USER; +use crate::constants::inner_constants::{DEFAULT_DEVICE, STANDARD_USER}; +use crate::dbconfig::schema::episodes::dsl::episodes; +use crate::dbconfig::schema::podcast_episodes::dsl::podcast_episodes; +use crate::dbconfig::schema::podcast_history_items::dsl::podcast_history_items; use crate::models::episode::{Episode, EpisodeAction}; use crate::models::misc_models::{ PodcastWatchedEpisodeModelWithPodcastEpisode, PodcastWatchedPostModel, @@ -7,10 +10,9 @@ use crate::models::podcast_episode::PodcastEpisode; use crate::models::podcasts::Podcast; use crate::service::mapping_service::MappingService; use crate::utils::error::{map_db_error, CustomError}; -use crate::DBType as DbConnection; +use crate::{insert_with_conn, DBType as DbConnection}; use chrono::{NaiveDateTime, Utc}; use diesel::sql_types::*; -use diesel::QueryId; use diesel::Queryable; use diesel::QueryableByName; use diesel::Selectable; @@ -18,6 +20,8 @@ use diesel::{ delete, insert_into, BoolExpressionMethods, ExpressionMethods, JoinOnDsl, OptionalExtension, QueryDsl, RunQueryDsl, }; +use diesel::{QueryId}; +use reqwest::Url; use utoipa::ToSchema; #[derive( @@ -124,7 +128,6 @@ impl PodcastHistoryItem { )?; if let Some(episode) = option_episode { if episode.action == EpisodeAction::Play.to_string() - && episode.position.unwrap() > found_history_item.watched_time && episode.timestamp > found_history_item.date { let found_podcast_item = @@ -160,7 +163,6 @@ impl PodcastHistoryItem { use crate::dbconfig::schema::podcast_history_items; use crate::dbconfig::schema::podcast_episodes::dsl::episode_id as eid; - use crate::dbconfig::schema::podcast_episodes::dsl::podcast_episodes; use crate::dbconfig::schema::podcast_history_items::dsl::episode_id as ehid; use diesel::NullableExpressionMethods; @@ -231,4 +233,61 @@ impl PodcastHistoryItem { .load::<(PodcastHistoryItem, PodcastEpisode, Podcast)>(conn) .map_err(map_db_error) } + + #[allow(clippy::redundant_closure_call)] + pub fn migrate_watchlog(conn: &mut DbConnection) { + use crate::dbconfig::schema::podcast_episodes::dsl as pe_dsl; + use crate::dbconfig::schema::podcast_episodes::table as ep_podcast; + use crate::dbconfig::schema::podcasts::dsl as p_dsl; + use crate::dbconfig::schema::podcasts::table as p_table; + + let history = podcast_history_items + .load::(conn) + .map_err(map_db_error) + .unwrap(); + + let mapped_episodes = history + .iter() + .map(|ph_item| { + let podcast = p_table + .filter(p_dsl::id.eq(ph_item.podcast_id)) + .first::(conn) + .unwrap(); + + let found_episode = ep_podcast + .filter(pe_dsl::episode_id.eq(ph_item.episode_id.clone())) + .first::(conn) + .unwrap(); + + let mut cleaned_url_parsed = Url::parse(&found_episode.url.clone()).unwrap(); + cleaned_url_parsed.set_query(None); + use rand::Rng; + let mut rng = rand::thread_rng(); + + let random_id = rng.gen_range(50000..100000); + Episode { + id: random_id, + username: ph_item.username.clone(), + device: DEFAULT_DEVICE.to_string(), + podcast: podcast.rssfeed, + episode: found_episode.url, + timestamp: ph_item.date, + + guid: Some(found_episode.guid.clone()), + action: "play".to_string(), + started: Some(0), + position: Some(ph_item.watched_time), + total: Some(found_episode.total_time), + cleaned_url: cleaned_url_parsed.to_string(), + } + }) + .collect::>(); + + mapped_episodes.iter().for_each(|v| { + insert_with_conn!(conn, |conn| diesel::insert_into(episodes) + .values(v) + .execute(conn) + .unwrap()); + }) + } } diff --git a/src/models/subscription.rs b/src/models/subscription.rs index 665fb021..443b9a4e 100644 --- a/src/models/subscription.rs +++ b/src/models/subscription.rs @@ -146,7 +146,8 @@ impl SubscriptionChangesToClient { dsl_types::username.eq(subscription.username), dsl_types::device.eq(subscription.device), dsl_types::podcast.eq(subscription.podcast), - dsl_types::created.eq(subscription.created))) + dsl_types::created.eq(subscription.created), + )) .execute(conn) .unwrap(); }