Add random quote endpoint
authorLanius Trolling <lanius@laniustrolling.dev>
Wed, 17 Jan 2024 13:30:01 +0000 (08:30 -0500)
committerLanius Trolling <lanius@laniustrolling.dev>
Wed, 17 Jan 2024 13:30:01 +0000 (08:30 -0500)
src/jvmMain/kotlin/info/mechyrdia/Factbooks.kt
src/jvmMain/kotlin/info/mechyrdia/lore/view_bar.kt
src/jvmMain/kotlin/info/mechyrdia/lore/views_quote.kt [new file with mode: 0644]
stuff/fixquotes.py [new file with mode: 0644]

index f2f6f8eefb40e4c35374c5718d1bb240926724ad..36316cd47c0c471c6b539bd22df931bf5251a948 100644 (file)
@@ -154,6 +154,20 @@ fun Application.factbooks() {
                        call.respondFile(call.galaxyMapPage())
                }
                
+               // Random quote
+               
+               get("/quote") {
+                       with(call) { respondHtml(HttpStatusCode.OK, randomQuote().toHtml("Random Quote")) }
+               }
+               
+               get("/quote.json") {
+                       call.respondText(randomQuote().toJson(), ContentType.Application.Json)
+               }
+               
+               get("/quote.xml") {
+                       call.respondText(randomQuote().toXml(), ContentType.Application.Xml)
+               }
+               
                // Routes for robots
                
                get("/robots.txt") {
index 5a9346b88d1ebc414d3fae1f686d088bcf149802..2cc0c8c9bd4ab9c8c72e87a5ad16e0e4c414f0e1 100644 (file)
@@ -25,7 +25,21 @@ data class NationProfileSidebar(val nationData: NationData) : Sidebar() {
                img(src = nationData.flag, alt = "Flag of ${nationData.name}", classes = "flag-icon")
                p {
                        style = "text-align:center"
-                       +nationData.name
+                       a(href = "https://www.nationstates.net/nation=${nationData.id}") {
+                               +nationData.name
+                       }
+               }
+       }
+}
+
+data class QuoteOriginSidebar(val author: String, val portrait: String, val link: String) : Sidebar() {
+       override fun TagConsumer<*>.display() {
+               img(src = "/assets/images/$portrait", alt = "Portrait of $author")
+               p {
+                       style = "text-align:center"
+                       a(href = "/lore/$link") {
+                               +author
+                       }
                }
        }
 }
diff --git a/src/jvmMain/kotlin/info/mechyrdia/lore/views_quote.kt b/src/jvmMain/kotlin/info/mechyrdia/lore/views_quote.kt
new file mode 100644 (file)
index 0000000..a38ede2
--- /dev/null
@@ -0,0 +1,80 @@
+package info.mechyrdia.lore
+
+import info.mechyrdia.Configuration
+import info.mechyrdia.JsonFileCodec
+import io.ktor.server.application.*
+import io.ktor.util.*
+import kotlinx.html.*
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.builtins.ListSerializer
+import kotlinx.serialization.json.buildJsonObject
+import kotlinx.serialization.json.put
+import java.io.File
+
+@Serializable
+data class Quote(
+       val quote: String,
+       val author: String,
+       val portrait: String,
+       val link: String
+) {
+       val fullPortrait: String
+               get() = if (portrait.startsWith("http://") || portrait.startsWith("https://"))
+                       portrait
+               else
+                       "https://mechyrdia.info/assets/images/$portrait"
+       
+       val fullLink: String
+               get() = if (link.startsWith("http://") || link.startsWith("https://"))
+                       link
+               else
+                       "https://mechyrdia.info/lore/$link"
+}
+
+fun loadQuotes(): List<Quote> {
+       val quotesJsonFile = File(Configuration.CurrentConfiguration.rootDir).combineSafe("quotes.json")
+       return JsonFileCodec.decodeFromString(ListSerializer(Quote.serializer()), quotesJsonFile.readText())
+}
+
+fun randomQuote(): Quote = loadQuotes().random()
+
+fun Quote.toXml(standalone: Boolean = true): String {
+       return buildString {
+               if (standalone)
+                       appendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
+               appendLine("<quote>")
+               append("<text>").append(quote.escapeHTML()).appendLine("</text>")
+               append("<author>").append(author.escapeHTML()).appendLine("</author>")
+               append("<portrait href=\"").append(fullPortrait.escapeHTML()).appendLine("\" />")
+               append("<link href=\"").append(fullLink.escapeHTML()).appendLine("\" />")
+               appendLine("</quote>")
+       }
+}
+
+fun Quote.toJson(): String {
+       return buildJsonObject {
+               put("text", quote)
+               put("author", author)
+               put("portrait", fullPortrait)
+               put("link", fullLink)
+       }.toString()
+}
+
+context(ApplicationCall)
+suspend fun Quote.toHtml(title: String): HTML.() -> Unit {
+       return page(title, standardNavBar(), QuoteOriginSidebar(author, portrait, link)) {
+               section {
+                       a { id = "page-top" }
+                       h1 { +title }
+                       blockQuote {
+                               +quote
+                       }
+                       p {
+                               style = "align:right"
+                               unsafe { raw("&#x2015;") }
+                               +Entities.nbsp
+                               a(href = "/lore/$link") { +author }
+                       }
+               }
+       }
+}
diff --git a/stuff/fixquotes.py b/stuff/fixquotes.py
new file mode 100644 (file)
index 0000000..e4e379f
--- /dev/null
@@ -0,0 +1,26 @@
+import json
+import re
+
+quote_pattern = re.compile(r"^\"(.*)\" \- (.*?)\|(.*?)\@(.*?)$")
+
+quote_list = []
+
+with open("../test/quotes.json", mode="r", encoding="utf-8") as quotes_json_file:
+       quote_list.extend(json.load(quotes_json_file))
+
+with open("../test/quotes.txt", mode="r", encoding="utf-8") as quotes_file:
+       for quote in quotes_file:
+               quote = quote.rstrip()
+               match = quote_pattern.fullmatch(quote)
+               
+               text, author, portrait, link = match.groups()
+               quote_dict = {
+                       "quote": text,
+                       "author": author,
+                       "portrait": "portrait-" + portrait.lower().replace(" ", "-").replace("'", ""),
+                       "link": link.removeprefix("https://mechyrdia.info/lore/")
+               }
+               quote_list.append(quote_dict)
+
+with open("../test/quotes.json", mode="w", encoding="utf-8") as quotes_json_file:
+       json.dump(quote_list, quotes_json_file, indent="\t")