From 951dc68394c8a316e1c0758d212b3600642ab514 Mon Sep 17 00:00:00 2001
From: Jonas L <jooola@users.noreply.github.com>
Date: Tue, 26 Jul 2022 14:16:34 +0200
Subject: [PATCH] feat(api): cast StreamSetting raw_value to value (#1991)

---
 api/libretime_api/core/models/preference.py   | 24 +++++++++++++++-
 .../core/tests/models/test_preference.py      | 28 +++++++++++++++++++
 api/schema.yml                                |  4 +--
 3 files changed, 53 insertions(+), 3 deletions(-)
 create mode 100644 api/libretime_api/core/tests/models/test_preference.py

diff --git a/api/libretime_api/core/models/preference.py b/api/libretime_api/core/models/preference.py
index 3e21f54c8..a2049bb87 100644
--- a/api/libretime_api/core/models/preference.py
+++ b/api/libretime_api/core/models/preference.py
@@ -1,5 +1,10 @@
+import logging
+from typing import Optional, Union
+
 from django.db import models
 
+logger = logging.getLogger(__name__)
+
 
 class Preference(models.Model):
     user = models.ForeignKey(
@@ -34,15 +39,32 @@ class StreamSetting(models.Model):
         max_length=64,
         db_column="keyname",
     )
-    value = models.CharField(
+    raw_value = models.CharField(
         max_length=255,
         blank=True,
         null=True,
+        db_column="value",
     )
     type = models.CharField(
         max_length=16,
     )
 
+    @property
+    def value(self) -> Optional[Union[bool, int, str]]:
+        # Ignore if value is an empty string
+        if not self.raw_value:
+            return None
+
+        if self.type == "boolean":
+            return self.raw_value.lower() == "true"
+        if self.type == "integer":
+            return int(self.raw_value)
+        if self.type == "string":
+            return self.raw_value
+
+        logger.warning(f"StreamSetting {self.key} has invalid type {self.type}")
+        return self.raw_value
+
     class Meta:
         managed = False
         db_table = "cc_stream_setting"
diff --git a/api/libretime_api/core/tests/models/test_preference.py b/api/libretime_api/core/tests/models/test_preference.py
new file mode 100644
index 000000000..e54f5b661
--- /dev/null
+++ b/api/libretime_api/core/tests/models/test_preference.py
@@ -0,0 +1,28 @@
+import pytest
+
+from ...models import StreamSetting
+
+
+# pylint: disable=invalid-name,unused-argument
+@pytest.mark.parametrize(
+    "type_name, value",
+    [
+        ("boolean", True),
+        ("integer", 1),
+        ("string", "hello"),
+    ],
+)
+def test_stream_setting_value(db, type_name, value):
+    setting = StreamSetting.objects.create(
+        key=f"some_{type_name}",
+        type=type_name,
+        raw_value=str(value),
+    )
+    assert isinstance(setting.value, type(value))
+
+    empty_setting = StreamSetting.objects.create(
+        key=f"some_empty_{type_name}",
+        type=type_name,
+        raw_value="",
+    )
+    assert empty_setting.value is None
diff --git a/api/schema.yml b/api/schema.yml
index e349def3f..5039f5fa6 100644
--- a/api/schema.yml
+++ b/api/schema.yml
@@ -6826,7 +6826,7 @@ components:
           type: string
           format: uri
           readOnly: true
-        value:
+        raw_value:
           type: string
           nullable: true
           maxLength: 255
@@ -7796,7 +7796,7 @@ components:
           type: string
           format: uri
           readOnly: true
-        value:
+        raw_value:
           type: string
           nullable: true
           maxLength: 255