Move SSD remote truth query to typed Kotlin

ober

c6553c467c5d03817b0900895d5b0c5feacd6746

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 7f3a039..90c6fb9 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -3628,6 +3628,26 @@
                   lower
                   "^172\\.(1[6-9]|2[0-9]|3[0-1])\\..*")))))))
 
+    (typed-kotlin-file "com/sfb/ssdreview/RemoteTruthQuery.kt"
+      (typed-library (com sfb ssdreview)
+        (export remoteTruthQuery)
+        (def (remoteTruthQuery (session : SsdSession)) : String
+          (string-append
+            "truth?compact=1&source_key="
+            (string-append
+              (urlEncode (SsdSession-sourceKey session))
+              (string-append
+                "&name="
+                (string-append
+                  (urlEncode (SsdSession-sourceName session))
+                  (string-append
+                    "&page="
+                    (string-append
+                      (int32->string (SsdSession-page session))
+                      (string-append
+                        "&dpi="
+                        (int32->string (SsdSession-dpi session))))))))))))
+
     (kotlin-file-lines "com/sfb/ssdreview/BoxTypes.kt"
       (
        "package com.sfb.ssdreview"
@@ -6402,13 +6422,7 @@
        ""
        "    fun pullRemoteTruth(session: SsdSession): Int {"
        "        return try {"
-       "            val relative = \"truth?\" + listOf("
-       "                \"compact=1\","
-       "                \"source_key=${urlEncode(session.sourceKey)}\","
-       "                \"name=${urlEncode(session.sourceName)}\","
-       "                \"page=${session.page}\","
-       "                \"dpi=${session.dpi}\""
-       "            ).joinToString(\"&\")"
+       "            val relative = remoteTruthQuery(session)"
        "            val connection = openPinnedConnection(relative, \"GET\", acceptGzip = true)"
        "            try {"
        "            val code = connection.responseCode"