From 423264879b48cb6542fe468aef6b3da9dfb935ce Mon Sep 17 00:00:00 2001
From: 0xb00bface <0xboobface@gmail.com>
Date: Fri, 3 Nov 2023 19:04:37 +0100
Subject: [PATCH] Add migration of model JSON before loading the models

---
 common/src/main/java/ctbrec/Config.java       | 40 +++++++++++++++++++
 .../main/java/ctbrec/MigrateModel5_1_2.java   | 22 ++++++++++
 .../java/ctbrec/io/json/dto/RecordingDto.java |  6 +++
 .../ctbrec/recorder/RecordingManager.java     | 11 +++++
 4 files changed, 79 insertions(+)
 create mode 100644 common/src/main/java/ctbrec/MigrateModel5_1_2.java

diff --git a/common/src/main/java/ctbrec/Config.java b/common/src/main/java/ctbrec/Config.java
index 99a3aeeb..bddba957 100644
--- a/common/src/main/java/ctbrec/Config.java
+++ b/common/src/main/java/ctbrec/Config.java
@@ -2,11 +2,14 @@ package ctbrec;
 
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import ctbrec.event.ModelPredicate;
 import ctbrec.io.IoUtils;
 import ctbrec.io.json.ObjectMapperFactory;
 import ctbrec.sites.Site;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
+import org.json.JSONArray;
+import org.json.JSONObject;
 
 import java.io.File;
 import java.io.IOException;
@@ -156,6 +159,7 @@ public class Config {
                     fileContent[2] = ' ';
                 }
                 String json = new String(fileContent, UTF_8).trim();
+                json = migrateJson(json);
                 settings = Objects.requireNonNull(mapper.readValue(json, Settings.class));
                 settings.httpTimeout = Math.max(settings.httpTimeout, 10_000);
                 if (settings.recordingsDir.endsWith("/")) {
@@ -179,6 +183,42 @@ public class Config {
         migrateOldSettings();
     }
 
+    private String migrateJson(String json) {
+        return migrateTo5_1_2(json);
+    }
+
+    private String migrateTo5_1_2(String json) {
+        JSONObject s = new JSONObject(json);
+
+        if (s.has("models")) {
+            JSONArray models = s.getJSONArray("models");
+            for (int i = 0; i < models.length(); i++) {
+                MigrateModel5_1_2.migrate(models.getJSONObject(i));
+            }
+        }
+
+        if (s.has("eventHandlers")) {
+            JSONArray eventHandlers = s.getJSONArray("eventHandlers");
+            for (int i = 0; i < eventHandlers.length(); i++) {
+                JSONObject eventHandler = eventHandlers.getJSONObject(i);
+                if (eventHandler.has("predicates")) {
+                    JSONArray predicates = eventHandler.getJSONArray("predicates");
+                    for (int j = 0; j < predicates.length(); j++) {
+                        JSONObject predicate = predicates.getJSONObject(j);
+                        if (Objects.equals(ModelPredicate.class.getName(), predicate.optString("type"))) {
+                            JSONArray models = predicate.getJSONArray("models");
+                            for (int k = 0; k < models.length(); k++) {
+                                JSONObject model = models.getJSONObject(k);
+                                MigrateModel5_1_2.migrate(model);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return s.toString();
+    }
+
     private void migrateOldSettings() {
     }
 
diff --git a/common/src/main/java/ctbrec/MigrateModel5_1_2.java b/common/src/main/java/ctbrec/MigrateModel5_1_2.java
new file mode 100644
index 00000000..8120769c
--- /dev/null
+++ b/common/src/main/java/ctbrec/MigrateModel5_1_2.java
@@ -0,0 +1,22 @@
+package ctbrec;
+
+import lombok.experimental.UtilityClass;
+import org.json.JSONObject;
+
+@UtilityClass
+public class MigrateModel5_1_2 {
+
+    private static final String MARKED_FOR_LATER = "markedForLater";
+    private static final String ADDED_TIMESTAMP = "addedTimestamp";
+
+    public static void migrate(JSONObject model) {
+        if (model.has(MARKED_FOR_LATER)) {
+            model.put("bookmarked", model.getBoolean(MARKED_FOR_LATER));
+            model.remove(MARKED_FOR_LATER);
+        }
+        if (model.has("ADDED_TIMESTAMP")) {
+            model.put("addedAt", model.optLong(ADDED_TIMESTAMP));
+            model.remove(ADDED_TIMESTAMP);
+        }
+    }
+}
diff --git a/common/src/main/java/ctbrec/io/json/dto/RecordingDto.java b/common/src/main/java/ctbrec/io/json/dto/RecordingDto.java
index 0c4f21ea..2e344557 100644
--- a/common/src/main/java/ctbrec/io/json/dto/RecordingDto.java
+++ b/common/src/main/java/ctbrec/io/json/dto/RecordingDto.java
@@ -1,6 +1,10 @@
 package ctbrec.io.json.dto;
 
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import ctbrec.Recording;
+import ctbrec.io.json.dto.converter.InstantToMillisConverter;
+import ctbrec.io.json.dto.converter.MillisToInstantConverter;
 import lombok.Data;
 
 import java.io.File;
@@ -12,6 +16,8 @@ import java.util.Set;
 public class RecordingDto {
     private String id;
     private ModelDto model;
+    @JsonSerialize(converter = InstantToMillisConverter.class)
+    @JsonDeserialize(converter = MillisToInstantConverter.class)
     private Instant startDate;
     private Recording.State status = Recording.State.UNKNOWN;
     private int progress = -1;
diff --git a/common/src/main/java/ctbrec/recorder/RecordingManager.java b/common/src/main/java/ctbrec/recorder/RecordingManager.java
index d2971a66..7ec03cda 100644
--- a/common/src/main/java/ctbrec/recorder/RecordingManager.java
+++ b/common/src/main/java/ctbrec/recorder/RecordingManager.java
@@ -2,6 +2,7 @@ package ctbrec.recorder;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import ctbrec.Config;
+import ctbrec.MigrateModel5_1_2;
 import ctbrec.Recording;
 import ctbrec.Recording.State;
 import ctbrec.RecordingSizeMonitor;
@@ -11,6 +12,7 @@ import ctbrec.io.json.mapper.RecordingMapper;
 import ctbrec.sites.Site;
 import ctbrec.sites.SiteUtil;
 import lombok.extern.slf4j.Slf4j;
+import org.json.JSONObject;
 import org.mapstruct.factory.Mappers;
 
 import java.io.File;
@@ -77,11 +79,13 @@ public class RecordingManager {
         if (metaFiles != null) {
             for (File file : metaFiles) {
                 String json = Files.readString(file.toPath());
+                json = migrateJson(json);
                 try {
                     Recording recording = Mappers.getMapper(RecordingMapper.class).toRecording(mapper.readValue(json, RecordingDto.class));
                     recording.setMetaDataFile(file.getCanonicalPath());
                     SiteUtil.getSiteForModel(sites, recording.getModel()).ifPresent(s -> recording.getModel().setSite(s));
                     recording.setMetaDataFile(file.getCanonicalPath());
+                    saveRecording(recording);
                     loadRecording(recording);
                 } catch (Exception e) {
                     log.error("Couldn't load recording {}", file, e);
@@ -90,6 +94,13 @@ public class RecordingManager {
         }
     }
 
+    private String migrateJson(String json) {
+        JSONObject r = new JSONObject(json);
+        JSONObject model = r.getJSONObject("model");
+        MigrateModel5_1_2.migrate(model);
+        return r.toString();
+    }
+
     private void loadRecording(Recording recording) throws IOException {
         if (recording.getStatus() == RECORDING || recording.getStatus() == GENERATING_PLAYLIST || recording.getStatus() == POST_PROCESSING) {
             recording.setStatus(WAITING);