import java.io.IOException
import java.util.concurrent.atomic.AtomicLong
-lateinit var application: Application
- private set
-
fun main() {
System.setProperty("logback.statusListenerClass", "ch.qos.logback.core.status.NopStatusListener")
}
fun Application.factbooks() {
- application = this
-
install(AutoHeadResponse)
install(IgnoreTrailingSlash)
import com.github.agadar.nationstates.shard.NationShard
import info.mechyrdia.OwnerNationId
-import info.mechyrdia.application
import info.mechyrdia.auth.NSAPI
import info.mechyrdia.auth.UserSession
import info.mechyrdia.auth.executeSuspend
import io.ktor.util.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
import java.util.concurrent.ConcurrentHashMap
@Serializable
val isBanned: Boolean = false
) : DataDocument<NationData> {
companion object : TableHolder<NationData> {
+ private val logger: Logger = LoggerFactory.getLogger(NationData::class.java)
+
override val Table = DocumentTable<NationData>()
override suspend fun initialize() {
}
fun unknown(id: Id<NationData>): NationData {
- application.log.warn("Unable to find nation with Id $id - did it CTE?")
+ logger.warn("Unable to find nation with Id $id - did it CTE?")
return NationData(id, "Unknown Nation", "https://www.nationstates.net/images/flags/exnation.png")
}
import com.jaredrummler.fontreader.truetype.TTFFile
import com.jaredrummler.fontreader.util.GlyphSequence
import info.mechyrdia.Configuration
-import info.mechyrdia.application
import info.mechyrdia.route.KeyedEnumSerializer
import info.mechyrdia.yieldThread
-import io.ktor.server.application.*
import io.ktor.util.*
import kotlinx.serialization.Serializable
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
import java.awt.Font
import java.awt.Shape
import java.awt.geom.AffineTransform
object TextAlignmentSerializer : KeyedEnumSerializer<TextAlignment>(TextAlignment.entries)
object MechyrdiaSansFont {
+ private val logger: Logger = LoggerFactory.getLogger(MechyrdiaSansFont::class.java)
+
fun renderTextToSvg(text: String, bold: Boolean, italic: Boolean, align: TextAlignment): String {
val (file, font) = getFont(bold, italic)
return layoutText(text, file, font, align).toSvgDocument(80.0 / file.unitsPerEm, 12.0)
return shape
} catch (ex: Exception) {
- application.log.error("Error converting text $text to font shape", ex)
+ logger.error("Error converting text $text to font shape", ex)
return GeneralPath()
} finally {
g2d.dispose()
import kotlinx.html.*
import java.time.Instant
-fun interface SECTIONS {
- fun section(body: SECTION.() -> Unit)
-}
-
-fun MAIN.sectioned(): SECTIONS = MainSections(this)
-
-private class MainSections(private val delegate: MAIN) : SECTIONS {
- override fun section(body: SECTION.() -> Unit) {
- delegate.section(block = body)
- }
-}
-
fun FlowOrPhrasingContent.dateTime(instant: Instant) {
span(classes = "moment") {
style = "display:none"
fun processCommentImage(url: String, domain: String) = "https://$domain/${url.sanitizeExtImgLink()}"
-fun processAnchor(param: String?): Map<String, String> = param?.let { mapOf("id" to it, "name" to it) }.orEmpty()
-
enum class FactbookFormattingTag(val type: HtmlLexerTag) {
B(HtmlTagLexerTag(attributes = mapOf("style" to "font-weight:bold"), tagMode = HtmlTagMode.INLINE, tagCreator = TagConsumer<*>::span.toTagCreator())),
I(HtmlTagLexerTag(attributes = mapOf("style" to "font-style:italic"), tagMode = HtmlTagMode.INLINE, tagCreator = TagConsumer<*>::span.toTagCreator())),
package info.mechyrdia.lore
-import info.mechyrdia.application
-import io.ktor.server.application.*
import io.pebbletemplates.pebble.PebbleEngine
import io.pebbletemplates.pebble.error.PebbleException
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
import java.io.StringWriter
object PreParser {
+ private val logger: Logger = LoggerFactory.getLogger(PreParser::class.java)
+
private val pebble = PebbleEngine.Builder()
.addEscapingStrategy("none", PebbleNoEscaping)
.defaultEscapingStrategy("none")
template.evaluate(writer, context)
return writer.toString()
} catch (ex: PebbleException) {
- application.log.error("Runtime error pre-parsing factbook $name", ex)
+ logger.error("Runtime error pre-parsing factbook $name", ex)
"[h1]Error[/h1]\n\nThere was a runtime error pre-parsing this factbook: ${ex.message}"
}
}
"icon.png",
)
+context(ApplicationCall)
+private fun HEAD.initialHead(pageTitle: String, ogData: OpenGraphData?) {
+ meta(charset = "utf-8")
+ meta(name = "viewport", content = "width=device-width, initial-scale=1.0")
+
+ meta(name = "theme-color", content = "#FFCC33")
+
+ ogData?.let { data ->
+ renderOgData(pageTitle, data)
+ }
+
+ link(rel = "icon", type = "image/svg+xml", href = "/static/images/icon.png")
+
+ title {
+ +pageTitle
+ }
+}
+
fun ApplicationCall.page(pageTitle: String, navBar: List<NavItem>? = null, sidebar: Sidebar? = null, ogData: OpenGraphData? = null, content: MAIN.() -> Unit): HTML.() -> Unit {
return {
pageTheme.attributeValue?.let { attributes["data-theme"] = it }
lang = "en"
head {
- meta(charset = "utf-8")
- meta(name = "viewport", content = "width=device-width, initial-scale=1.0")
-
- meta(name = "theme-color", content = "#FFCC33")
-
- ogData?.let { data ->
- renderOgData(pageTitle, data)
- }
+ initialHead(pageTitle, ogData)
for (font in preloadFonts)
link(
attributes["as"] = "image"
}
- link(rel = "icon", type = "image/svg+xml", href = "/static/images/icon.png")
-
link(rel = "stylesheet", type = "text/css", href = "/static/style.css")
request.queryParameters["redirect"]?.let { redirect ->
}
script(src = "/static/init.js") {}
-
- title {
- +pageTitle
- }
}
body {
div { id = "bg" }
lang = "en"
head {
- meta(charset = "utf-8")
- meta(name = "viewport", content = "width=device-width, initial-scale=1.0")
-
- meta(name = "theme-color", content = "#FFCC33")
-
- ogData?.let { data ->
- renderOgData(pageTitle, data)
- }
-
- link(rel = "icon", type = "image/svg+xml", href = "/static/images/icon.png")
+ initialHead(pageTitle, ogData)
link(rel = "stylesheet", type = "text/css", href = "/static/raw.css")
-
- title {
- +pageTitle
- }
}
body {
content()
}.toString()
}
+context(Quote)
+private fun FlowContent.quoteWithAttribution() {
+ h1 { +title }
+ blockQuote {
+ +quote
+ }
+ p {
+ style = "align:right"
+ unsafe { raw("―") }
+ +Entities.nbsp
+ a(href = fullLink) { +author }
+ }
+}
+
context(ApplicationCall)
suspend fun Quote.toHtml(title: String): HTML.() -> Unit {
return page(title, standardNavBar(), QuoteOriginSidebar(author, fullPortrait, fullLink)) {
section {
a { id = "page-top" }
- h1 { +title }
- blockQuote {
- +quote
- }
- p {
- style = "align:right"
- unsafe { raw("―") }
- +Entities.nbsp
- a(href = fullLink) { +author }
- }
+ quoteWithAttribution()
}
}
}
context(ApplicationCall)
fun Quote.toRawHtml(title: String): HTML.() -> Unit {
return rawPage(title) {
- h1 { +title }
- blockQuote {
- +quote
- }
- p {
- style = "align:right"
- unsafe { raw("―") }
- +Entities.nbsp
- a(href = fullLink) { +author }
- }
+ quoteWithAttribution()
p {
style = "align:center"
a(href = fullLink) {