From c6049f543b587999d2ce4b79c89706589d540556 Mon Sep 17 00:00:00 2001 From: Lanius Trolling Date: Wed, 14 Dec 2022 17:31:55 -0500 Subject: [PATCH] Change Tylan numerals --- build.gradle.kts | 13 +- src/main/kotlin/info/mechyrdia/Factbooks.kt | 184 ++++++++++-------- .../info/mechyrdia/lore/tylan_language.kt | 3 + .../font/tylan-language-alphabet-3.woff | Bin 4636 -> 4692 bytes src/main/resources/static/style.css | 14 +- 5 files changed, 117 insertions(+), 97 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a8ce5c1..ea7c65e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,13 +22,14 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") - implementation("io.ktor:ktor-server-netty:2.1.3") - implementation("io.ktor:ktor-server-html-builder:2.1.3") + implementation("io.ktor:ktor-server-netty:2.2.1") + implementation("io.ktor:ktor-server-html-builder:2.2.1") - implementation("io.ktor:ktor-server-call-id:2.1.3") - implementation("io.ktor:ktor-server-call-logging:2.1.3") - implementation("io.ktor:ktor-server-forwarded-header:2.1.3") - implementation("io.ktor:ktor-server-status-pages:2.1.3") + implementation("io.ktor:ktor-server-call-id:2.2.1") + implementation("io.ktor:ktor-server-call-logging:2.2.1") + implementation("io.ktor:ktor-server-forwarded-header:2.2.1") + implementation("io.ktor:ktor-server-sessions-jvm:2.2.1") + implementation("io.ktor:ktor-server-status-pages:2.2.1") implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.8.0") diff --git a/src/main/kotlin/info/mechyrdia/Factbooks.kt b/src/main/kotlin/info/mechyrdia/Factbooks.kt index 8f6db51..19dff0e 100644 --- a/src/main/kotlin/info/mechyrdia/Factbooks.kt +++ b/src/main/kotlin/info/mechyrdia/Factbooks.kt @@ -1,3 +1,5 @@ +@file:JvmName("Factbooks") + package info.mechyrdia import info.mechyrdia.lore.* @@ -15,100 +17,112 @@ import io.ktor.server.plugins.statuspages.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* +import io.ktor.server.sessions.* +import io.ktor.util.* import org.slf4j.event.Level import java.io.File import java.io.IOException import java.util.concurrent.atomic.AtomicLong -object Factbooks { - @JvmStatic - fun main(args: Array) { - System.setProperty("logback.statusListenerClass", "ch.qos.logback.core.status.NopStatusListener") +fun main() { + System.setProperty("logback.statusListenerClass", "ch.qos.logback.core.status.NopStatusListener") + + System.setProperty("io.ktor.development", "false") + + embeddedServer(Netty, port = Configuration.CurrentConfiguration.port, host = Configuration.CurrentConfiguration.host, module = Application::factbooks).start(wait = true) +} + +fun Application.factbooks() { + install(IgnoreTrailingSlash) + install(XForwardedHeaders) + + install(CallId) { + val counter = AtomicLong(0) + generate { + "call-${counter.incrementAndGet().toULong()}-${System.currentTimeMillis()}" + } + } + + install(CallLogging) { + level = Level.INFO - System.setProperty("io.ktor.development", "false") + callIdMdc("ktor-call-id") - embeddedServer(Netty, port = Configuration.CurrentConfiguration.port, host = Configuration.CurrentConfiguration.host) { - install(IgnoreTrailingSlash) - install(XForwardedHeaders) - - install(CallId) { - val counter = AtomicLong(0) - generate { - "call-${counter.incrementAndGet().toULong()}-${System.currentTimeMillis()}" - } - } - - install(CallLogging) { - level = Level.INFO - - callIdMdc("ktor-call-id") - - format { call -> - "Call #${call.callId} Client ${call.request.origin.remoteHost} `${call.request.userAgent()}` Request ${call.request.httpMethod.value} ${call.request.uri} Response ${call.response.status()}" - } - } + format { call -> + "Call #${call.callId} Client ${call.request.origin.remoteHost} `${call.request.userAgent()}` Request ${call.request.httpMethod.value} ${call.request.uri} Response ${call.response.status()}" + } + } + + /* + install(Sessions) { + cookie("USER_SESSION", SessionStorageMongoDB()) { + identity { Id().id } - install(StatusPages) { - status(HttpStatusCode.NotFound) { call, _ -> - call.respondHtml(HttpStatusCode.NotFound, call.error404()) - } - - exception { call, (url, permanent) -> - call.respondRedirect(url, permanent) - } - exception { call, _ -> - call.respondHtml(HttpStatusCode.BadRequest, call.error400()) - } - exception { call, _ -> - call.respondHtml(HttpStatusCode.NotFound, call.error404()) - } - exception { call, _ -> - call.respondHtml(HttpStatusCode.NotFound, call.error404()) - } - - exception { call, ex -> - call.application.log.error("Got uncaught exception from serving call ${call.callId}", ex) - - call.respondHtml(HttpStatusCode.InternalServerError, call.error500()) - throw ex - } - } + cookie.extensions["SameSite"] = "lax" + cookie.extensions["Secure"] = null + } + } + */ + + install(StatusPages) { + status(HttpStatusCode.NotFound) { call, _ -> + call.respondHtml(HttpStatusCode.NotFound, call.error404()) + } + + exception { call, (url, permanent) -> + call.respondRedirect(url, permanent) + } + exception { call, _ -> + call.respondHtml(HttpStatusCode.BadRequest, call.error400()) + } + exception { call, _ -> + call.respondHtml(HttpStatusCode.NotFound, call.error404()) + } + exception { call, _ -> + call.respondHtml(HttpStatusCode.NotFound, call.error404()) + } + + exception { call, ex -> + call.application.log.error("Got uncaught exception from serving call ${call.callId}", ex) - routing { - get("/") { - redirect("/lore") - } - - static("/static") { - resources("static") - } - - get("/lore/{path...}") { - call.respondHtml(HttpStatusCode.OK, call.loreArticlePage()) - } - - static("/assets") { - files(File(Configuration.CurrentConfiguration.assetDir)) - } - - get("/change-theme") { - call.respondHtml(HttpStatusCode.OK, call.changeThemePage()) - } - - post("/change-theme") { - val newTheme = when (call.receiveParameters()["theme"]) { - "light" -> "light" - "dark" -> "dark" - else -> "system" - } - call.response.cookies.append("factbook-theme", newTheme, maxAge = Int.MAX_VALUE.toLong()) - redirect("/lore") - } - - post("/tylan-lang") { - call.respondText(TylanAlphabet.tylanToFontAlphabet(call.receiveText())) - } + call.respondHtml(HttpStatusCode.InternalServerError, call.error500()) + throw ex + } + } + + routing { + get("/") { + redirect("/lore") + } + + static("/static") { + resources("static") + } + + get("/lore/{path...}") { + call.respondHtml(HttpStatusCode.OK, call.loreArticlePage()) + } + + static("/assets") { + files(File(Configuration.CurrentConfiguration.assetDir)) + } + + get("/change-theme") { + call.respondHtml(HttpStatusCode.OK, call.changeThemePage()) + } + + post("/change-theme") { + val newTheme = when (call.receiveParameters()["theme"]) { + "light" -> "light" + "dark" -> "dark" + else -> "system" } - }.start(wait = true) + call.response.cookies.append("factbook-theme", newTheme, maxAge = Int.MAX_VALUE.toLong()) + redirect("/lore") + } + + post("/tylan-lang") { + call.respondText(TylanAlphabet.tylanToFontAlphabet(call.receiveText())) + } } } diff --git a/src/main/kotlin/info/mechyrdia/lore/tylan_language.kt b/src/main/kotlin/info/mechyrdia/lore/tylan_language.kt index 2d0bb12..1a88a51 100644 --- a/src/main/kotlin/info/mechyrdia/lore/tylan_language.kt +++ b/src/main/kotlin/info/mechyrdia/lore/tylan_language.kt @@ -11,6 +11,9 @@ object TylanAlphabet { ) private val replacements = listOf( + Regex("([0-9xy]+)(?!\\s)") to "$1 ", + Regex("(?n*fkDDtvAqWPU>gxj#fY>fu0JQ)5Yrp^3 z{x|;rO<&)_gy^S4r0hg-z8Fu(8R+Wi6B#ejW+93dxC#KKccf$i0Fq6#ZxV&{VRgr& zJRLCr0JS38$HcizWk1(y7e_yk2rsh|A>}_22mpzT$3rv#kO~3-%n1N^vz<3kpIx0D ziDQT~(TBJ(0O$FwtLsXHL`LNQNk)(oLe}Z(=^spFt3>8Y>}w-Ail{uiQA9ryGa?%! zY7UpOW$x)1OpFVO005AfF)<3@514p4dO8CDT>>%7?*KrdRT{i+iShRH2LOhDLF$M) zqYI>63eH6#osdXi4gwY zuvMITfw)VOnGLL+mu5@xQ?I^N{7$_s24PZ|TP^&hS&{w0A#g6Ie&8@WFDrEFkTChA0j=Bnnsr&@qWXHROES-V*; zCU=?tOIX|n4G-IeXx{~aJ_CU?bQFO;c0e{#FcJX9tYZR!fFq<_Xq;&r5V{DJgsqFL zb1bwhCOZXY6`_>QM?Exx?t_Tk*Aa1Yf?hUuRf%{uBvIk9&6#UErv|o!o%)lTSV-9$x0Sl0$F9{GF~I+!orF*&d(X#q?ow9O<^>JVukW< zwy3pewa~Ua3f|poUA}|6iOcB?irnRHV{fAcp&%PU@WSq__jr-A8X2h#g+b9!b-+$i z9{hKo&#ec&IQp3?%hm-ROILH`G8<5mHqU1!bfJaJa|&Z+`uG!Q1o8as{!&G;KZehA zYO{xjK>gFGP_0Ri&upuzvXEzbsZxfuAB^FCyOlwTMlum%{?4$4mHfG6Za6LAsM9lc`$fiH28{c%*Iv`>l62uxSBbta zv>pswk*8!o=+9NJGQ&AEorN}|7tTbi0*V7+%-!K9oM zuFxK?9rgglHXk4KM!rgEWyGwk;N2kj)Tgm3={9AP=#zJ19$4|zyX7QR+EJsY_<6PD z-LO>EVV8&ZiXUc{*uoX!pPHFCFIe0eKPLXEu+C{d#mK-eEqyMY1LZk~2R24r)6(%e z7EfUK^rEFR?ojd|wpYsi^ZE>*K!|9?5IM)RXt!caVsaB{kz9RnCyX*W9#65F#!-tr z(Wza*j~bjhI?GW|XfADLN86(7N_xbs7!YfdwYMyJIgaDVLuN2@;nL6aadx?pyfLO- zqTk#ZPkT4zX0!zMmf)4g0-u)7-JaY}(ncMbxh)^@#4$u|p`cNLjm$0J{_GI4gR@LY zKK`Qfq1Ux{u<`9x^^sqQ$X2Pq@y1Xq_oAIiP4$YPx6NtJs{y@j&)$bJ&+ef?tkHT7;y8~-q zTJZc_uGgj9Mtia>TW{`xqbt_p&9P%^C~L`|mPq&?{#GKtE5C@F z;hw@vh)2%!7ZeNFTvDowZ)aF5;~wl7vK0=fTiEnS!8WE^&9;A%ek=2_r~l!E{+HW> zE0*{|%>!1^^t)LkY;4>$i;;$s`9eNi(bw(wFn3hv5bATR*Ob_zm9c>!|lI}h2zg8JQ==iDr3i=l|H~2jQdDz;T!55}o8T$kh zsSvyS#Gl?!wL`RkRu(#AI5_aysqCt)(cmHCV}ByT{d|*u9(?o_MQR{Rj(d%zbuOTSbZj#aUH9|xS*5s+}^4pGSuVZZ56J5@N3XO zXAdqWv7ELQ=XgG5WZsnUICSa^;Uc^oS!*;JXnzofe@-ty23l`w!h8rU94eX?+?R!> zF6uTp_2Bi?$Y^eN!O+&0H}g*^)Seb_W#AdEE1o4Ok%2YOQ~y})j4x}Pf*tYVy^(74 zutqa%Wzu2Ru|(}_&O9}=ZZZ?uP(ng@d-5AQ=e{(Fn|Na?_&tEy<{L@kTE6g_Yb5S8 zM$XgYMZhnw>NSOi)Hmf@5+J3m+Iped!e*M(%U#;W<9lzQm}L=;wdpH8veCZWWdQ~z z+7UG2j^GdDw=?!a4kzZx<>JxIlyqOLXwPOqo$#||U+Ous_qtIbt0f(-|v6QxY`(tHQ zkXyiwTb>M_lZYMh+fy&jQ1eyn`WxXMDI3(Wj$nij_dz7WPU??MXkYo2#xOaqvCPAf zJi^{as{oP4KC$ZLBPr7p}Y^>2b*(prZwql!2nwxy_OV-1-0p1 zDoQi~R-tmlIl0Ot5UN)6KEaS>c;htm`997%G2#K8LetTXsvH-^5j+rolsRiLa5~(* zM(R15)G14@2J2G7Tg+kV-bflUb6~=;E#T)36`_{IQ?J6N5%t+XRK|Ui7C6rdb#`6s+j2j$~5&kkr}7mXVaPaG*UXa zScOvLhMhmxZb%cy{q4~2M&2|Z+~WNfDL;4=@EeTozWDNZlQAouS=1Qsz0{QVa~*u; zT^mta7_q3?-SoZPKbl!v{L)lKlI@htEB~w=QMb5nzIMHy{96y~QNK0tr#9#<_lHKS zaQ?a;z1?-bMA{a1d`x}=mi?YyM?O5FH|ijcj#_h7Ps&T#KNSM91V?p4yzZQp>NGT( zub7(nKaQDhE*?yJ`174Hv&2d%w<0K%gDDKA6ra#x{i;pwJ(%T=o2Xr>n73s1sWX2U zv(RjJ<-=DQ(@|_7-ic&m5HD$L`ffeNMk#M%V&uD$0}4m?=#Ivj zsbXKx>%S*~w%}^Gmr{niW0i06ro|w0zRW_mZyX=N{ESk8w%Fb-PzjPWED6e+;yW;! z>7-4^fq6Xgpi(e=YFt$MAU)mI&)tPbrF?B&aVh2F36oXM4VT!(gDdRH>QV;XZ&^DD zpMPB`hvh3#tLXh?n98*q653$2(y3d)JoQbXVh|KOeu~soAJe1u$ zEs5}lbMN|vB*T^S3mSx0yR`Q&&HrHOjV+R&PkSbG_w5##nnaaY;u0U+4$Y;Pxnse} zT4?(<#qFNKw{`E*3nsg42W-RqUkxyNF<_ej7_HUreK4e3f`W)^BmfYxZ2II|#cWQQ z-6L;3j%Lg4R|$&yKVds4+fF@0rD!4huzoPYp*^4e&&5Hiq=BZ{d$kkoP8g$@d4+Ci zg6!=zF^e+uO8rWeLw0$$u?oHNY`D)a75|@Ol?GKY>gVJ%?6MwR?__X7#xG?(dn%L< zm?du9tM$;kG3!~Tum$&+t(8RezQ6vLj#I^VyQ@@gc(0}VACm_nELrx>&$KSt%vzV^{ Kl9Xxz0R9KDQaZ!{ delta 3882 zcmY+HcRbbKAICqgEqjNHQnt+OJhm&(YB%xlHfwNf^5 zkz~6@k#T>w@Av!9?>ru_b3U)<=XKUU=ka)tUcy{Lg+q*u0SbWJ*aZNlzoU%Lzy9y{ z|2Jb}8w+yoFXSUj;Q4i@A`?R+V*p?ykiFnPk^n*=P+0{4pumv58CkGkUcXsH06Yi) zKsIE*OaAxtyy|0SZ+Hlb4A~~hknXQYB!JS}Kf((Ds009jK^g#r=-wp!&hYVsdypr| zku&6l0cEiK>7)-Ck{Ou;V6raJgj1*b1cV~V>?hg#lE>Nz&U$M9Km<8Qd5z4zkTu&K zfFBQlBgy+x!~p;b;3Y$0AOx_y4G-`H0A_L!Gy?#%dT)_LyP&|3Q1SsUku&efI$>sI zA|NpcmKQ(toA;*Gv2E=&uEM($8ElUM#P(C4`Whj{`NqBKeXz|jtL{pId#h>QXX zT~ve2xju3*<;DzChcMmC-Y^4jPtni#u_p|s!f`AXS8&}+A74`x#Bt>Aeb+p?A|)!i z10KDp?>R1@|D(@YqyNv5^FFp9B9?89;-1S%8~3hPJIjGhdGIs82UJ(LXQYU~q!%N= z9cLOHETB0>o_`MogLy^6&eIsvu%doa?DBR-a>s*&Wjcic&IQ;t(C!*LT9j(B_yG7xt4R~JS^f)7tNQa~n5({bgM2Co4CpD8iNp*r$ z+B*r;F=t>$y_Y0Q-RPz?FgP19u1Zo`=i3 z!J@iOVvUkK`TEuD)W(5vwThO>#>tpT^-1NLHn<907E#cJjeo#G%aXu^<4kqJ_+q>; zGMIioxo18CMXc@EHDsE3BC){xPyo5LLX>gC*)zH`%`>j*z%{^ zy3gy6^s+lgi)Tw;dD7u{*>$R8jn4iP+S!PPiqig;3Ka;$ZgNH$Rw(coEQPVc543k% zXM$0OVscy&AND7-w%arS?b&lJidtHyhkw@9y?qe4#dMlkgfnluXeJfOf;70ZnW2dEJlwMl}#BwdW%94oWLOqf7 zLhC>vM>%rq9+FT8F&>c%=r;8#qBS4OBmUaW!^;@Uh;D>VY*Vx0qNb zSDg4QD+zadx~>}+u+iI6vLo?-J(4_x)Q>giPnG*L+$i*ZW=BkVn{9cd!b^K`O?j29l`_iL@ZUOxW5apT#| zjgBpemmVc_O5D+La$6L=dVF2a=gYs~H>+>QSNcp{VSAdm;WmQd;|ACH=g@Of&dI%m zqY2(K6Ss0t_2xSI4I`6?FG_p3S0`z2GnH^vMZ+t2{EVC&8?=r$kjJPUjE^j19j}Mz zqr1ix9NV3#L;NN8@+ZHUmVU{YsgY(AOj|5T%bClbRxf_dF`Q#{so9ol^HCV+5-VC) zX%fF|vAH+2VxbeG5K!nlb%XQBq4z{JYj9RPixzM0q&mQ?R!4o`zn>j4jn|c45JXb} zcCVfDo;Iepo-NPvAz6c?1$<}}{a7jVqEJ^L zxcgz^8t$zW)TXZ#Djpe;8mL`0HO$q632ja>5Ea-^+`Is#@EqJ4n{~`}WK>Y#cz1`d zazi-I-<|Sfmh%OaLLw6YuWPn%$O|%aj+-HcqPNp?J(p+~bWELEe)orP@dU?r(uFAW zV)7~gsAznbO?uhWwP%P#sur`zJ+;%C`XhO#ZF`}E&Rn)e;a_;J59(Y~xgk8(FQe9M zVKFzS+p2X$BzI5T8-u4`d_4|~Jiskg;y&TO0Xr9_HX!_w5~^wD7`mHDsv9U-Qc14D>}l$wOa zaK8uQOYYvNr=`C}GMlTvih7{?MtW-PE`vqWu=6xWEbyiC3aQ z=?TQI;4hjduk0K?;#KbFesI0T1&3m6pg!-7q^y2&6Z_oyq@QdHmYgiL4x$Zg<#gn6aIXOgc z;cIAxw!d^y3o=$^PN)BK4dd`RDOrPt=dX`Yj6K&oZA-k}XdDZFz59-DU=3^bPZW1w zt6n(b=I7AT?$oKn<2!bzAkN$IDcbFYQ^71si*wJ0Ti?9a-HW$V+02yM%6w6MS*yBW zSWB+i#OPa9sj?JChH<2g_xZrt@%9C+q?mVzUe4Gqlib4MOg&kKMMFcu@ir zHA+!ccl0@TO}w_L-nP0);m4PuaBXF=Ql2eZ_dJj=&YkbRdI0}DBKNBlk#zWAS^E$5 zi!F(bbEYsBPpUNR0pL9LG}5)-ca+z*;ZbWw!_YAKq-?dKoFOyXpD zsttt(yjOz}>X#qli{hzcZp^113(PbSr0nsJJu=YqMUTJv3%{|VgwgwUJyZ^{8ID2U zzpH!Qpf0QA-du*m=U_p<*m){`Ree6+$N*lGE`!R~vk`5}`RUtLU7&$g;Ey-5G_BaQXt_@xFxKEG{DCd2fS z+IY9kqWDIEw@&d8e66P`HKI#IrQyyst+zjY(!D*uudGMZ&!0w+B&?*^I~E+lLiQiq zL{c>rrgYooqkJ~2l6!4L6}xg+kl#BU+f?$CO_10XA$Foa-@OrO>f(x{>^G>6CT4$s ziy_rUV~?H@iq!`lZwk{6RnTg08{`TznJz2`+o5|g7olh4k8^u57_oH>Cf#C4^m`?} z1`+l#f#9l2Z-;My+?)!vn$F8*HS6a*7*7bjq2F%DidAAae|poe-6VaddG^G*KlyWY z=gih=K|66Se1in^2SW>xm^w7`90)aWC6)rvU4W!ao4&35RbhL7`;D#5Ku%&K#|PKW zW8PuIF2zHR4?~|KqD8(xN$4OU8S!jSr65=k{1KW{%Bsw~iGeM%%+R)+4O(v5Mw61G zJcHPA?(QEHwm?>E#+os=c*RO36?%yc)`y1{>@ z#t$-$rA$yr70?J?8)!P`nElSVC3t