Skip to content

Commit fcc1b67

Browse files
committed
Fix canonical history ID migration
1 parent 77304b3 commit fcc1b67

3 files changed

Lines changed: 38 additions & 31 deletions

File tree

scripts/remap_trakt_watched.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class EpisodeRow:
4444

4545

4646
def episode_history_id(series: SeriesRow, episode: EpisodeRow) -> str:
47-
key = f"imdb/{series.imdb}" if series.imdb else f"redseat/{series.id}"
47+
imdb = series.imdb.strip() if series.imdb else ""
48+
key = f"imdb/{imdb}" if imdb else f"redseat/{series.id}"
4849
return f"episode:{key}/{episode.season}/{episode.number}"
4950

5051

src/model/history.rs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ use super::{
1515

1616
const HISTORY_MIGRATION: &str = "canonical_history_ids_v4";
1717

18+
fn non_empty_id(id: Option<&str>) -> Option<&str> {
19+
id.map(str::trim).filter(|id| !id.is_empty())
20+
}
21+
1822
fn series_history_key(serie: &Serie) -> String {
19-
serie
20-
.imdb
21-
.as_ref()
23+
non_empty_id(serie.imdb.as_deref())
2224
.map(|imdb| format!("imdb/{imdb}"))
2325
.unwrap_or_else(|| format!("redseat/{}", serie.id))
2426
}
@@ -28,9 +30,7 @@ pub fn series_history_id(serie: &Serie) -> String {
2830
}
2931

3032
pub fn movie_history_id(movie: &Movie) -> String {
31-
movie
32-
.imdb
33-
.as_ref()
33+
non_empty_id(movie.imdb.as_deref())
3434
.map(|imdb| format!("movie:imdb/{imdb}"))
3535
.unwrap_or_else(|| format!("movie:redseat/{}", movie.id))
3636
}
@@ -121,7 +121,7 @@ fn episode_legacy_ids(serie: &Serie, episode: &Episode) -> HashSet<String> {
121121
.collect();
122122

123123
for key in [
124-
serie.imdb.as_ref().map(|id| format!("imdb/{id}")),
124+
non_empty_id(serie.imdb.as_deref()).map(|id| format!("imdb/{id}")),
125125
serie.tmdb.map(|id| format!("tmdb/{id}")),
126126
serie.tvdb.map(|id| format!("tvdb/{id}")),
127127
Some(format!("redseat/{}", serie.id)),
@@ -160,8 +160,22 @@ fn unique_candidates<T>(candidates: HashMap<String, HashSet<T>>) -> HashMap<Stri
160160

161161
fn is_current_history_id(kind: &MediaType, id: &str) -> bool {
162162
match kind {
163-
MediaType::Movie => id.starts_with("movie:imdb/") || id.starts_with("movie:redseat/"),
164-
MediaType::Episode => id.starts_with("episode:imdb/"),
163+
MediaType::Movie => ["movie:imdb/", "movie:redseat/"]
164+
.into_iter()
165+
.any(|prefix| non_empty_id(id.strip_prefix(prefix)).is_some()),
166+
MediaType::Episode => {
167+
let Some(path) = id.strip_prefix("episode:imdb/") else {
168+
return false;
169+
};
170+
let mut parts = path.split('/');
171+
matches!(
172+
(parts.next(), parts.next(), parts.next(), parts.next()),
173+
(Some(imdb), Some(season), Some(number), None)
174+
if non_empty_id(Some(imdb)).is_some()
175+
&& season.parse::<u32>().is_ok()
176+
&& number.parse::<u32>().is_ok()
177+
)
178+
}
165179
_ => true,
166180
}
167181
}
@@ -354,38 +368,25 @@ impl ModelController {
354368

355369
pub async fn migrate_series_history_ids(
356370
&self,
357-
library_id: &str,
358371
old_serie: &Serie,
359372
new_serie: &Serie,
360373
) -> crate::Result<()> {
361-
if series_history_id(old_serie) == series_history_id(new_serie) {
374+
let old_prefix = format!("episode:{}/", series_history_key(old_serie));
375+
let new_prefix = format!("episode:{}/", series_history_key(new_serie));
376+
if old_prefix == new_prefix {
362377
return Ok(());
363378
}
364379

365-
let store = self.store.get_library_store(library_id)?;
366-
let episode_targets: HashMap<String, String> = store
367-
.get_episodes(EpisodeQuery {
368-
serie_ref: Some(new_serie.id.clone()),
369-
..Default::default()
370-
})
371-
.await?
372-
.into_iter()
373-
.map(|episode| {
374-
(
375-
episode_history_id(old_serie, &episode),
376-
episode_history_id(new_serie, &episode),
377-
)
378-
})
379-
.collect();
380380
let watched_rewrites = self
381381
.store
382382
.get_all_watched()
383383
.await?
384384
.into_iter()
385385
.filter(|row| row.kind == MediaType::Episode)
386386
.filter_map(|row| {
387+
let suffix = row.id.strip_prefix(&old_prefix)?;
387388
Some(HistoryIdRewrite {
388-
new_id: episode_targets.get(&row.id)?.clone(),
389+
new_id: format!("{new_prefix}{suffix}"),
389390
kind: row.kind,
390391
old_id: row.id,
391392
user_ref: row.user_ref?,
@@ -399,8 +400,9 @@ impl ModelController {
399400
.into_iter()
400401
.filter(|row| row.kind == MediaType::Episode)
401402
.filter_map(|row| {
403+
let suffix = row.id.strip_prefix(&old_prefix)?;
402404
Some(ProgressIdRewrite {
403-
new_id: episode_targets.get(&row.id)?.clone(),
405+
new_id: format!("{new_prefix}{suffix}"),
404406
new_parent: Some(series_history_id(new_serie)),
405407
kind: row.kind,
406408
old_id: row.id,

src/model/series.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,12 @@ impl ModelController {
381381
"get_serie".to_string(),
382382
))?
383383
.item;
384+
let mut updated_serie = old_serie.clone();
385+
if let Some(imdb) = &update.imdb {
386+
updated_serie.imdb = Some(imdb.clone());
387+
}
388+
self.migrate_series_history_ids(&old_serie, &updated_serie)
389+
.await?;
384390
store.update_serie(&serie_id, update).await?;
385391
let serie = store
386392
.get_serie(&serie_id)
@@ -391,8 +397,6 @@ impl ModelController {
391397
"get_serie".to_string(),
392398
))?
393399
.item;
394-
self.migrate_series_history_ids(library_id, &old_serie, &serie)
395-
.await?;
396400
self.send_serie(SeriesMessage {
397401
library: library_id.to_string(),
398402
series: vec![SerieWithAction {

0 commit comments

Comments
 (0)