Initial commit

Este commit está contenido en:
kageru 2019-09-19 22:04:23 +02:00
commit e80c97e450
Firmado por: kageru
ID de clave GPG: 8282A2BEA4ADA3D2
Se han modificado 8 ficheros con 211 adiciones y 0 borrados

3
.gitignore vendido Archivo normal
Ver fichero

@ -0,0 +1,3 @@
.gradle/
build/
kodeshare.log

32
build.gradle.kts Archivo normal
Ver fichero

@ -0,0 +1,32 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.3.50"
application
}
group = "moe.kageru"
version = "0.1.0"
val mainClass = "moe.kageru.kodeshare.KodeshareKt"
application {
mainClassName = mainClass
}
val ktorVersion = "1.2.4"
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation("io.ktor:ktor-server-netty:$ktorVersion")
implementation("io.ktor:ktor-locations:$ktorVersion")
implementation("org.jetbrains.exposed:exposed:0.17.3")
implementation("org.mariadb.jdbc:mariadb-java-client:2.4.4")
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}

1
gradle.properties Archivo normal
Ver fichero

@ -0,0 +1 @@
kotlin.code.style=official

2
settings.gradle Archivo normal
Ver fichero

@ -0,0 +1,2 @@
rootProject.name = 'kodeshare'

Ver fichero

@ -0,0 +1,22 @@
package moe.kageru.kodeshare
import io.ktor.application.install
import io.ktor.features.DefaultHeaders
import io.ktor.locations.Locations
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import moe.kageru.kodeshare.Routes.createRoutes
@ExperimentalStdlibApi
fun main() {
embeddedServer(Netty, 9092) {
install(DefaultHeaders)
install(Locations)
routing {
createRoutes()
}
}.start(wait = true)
}
data class Paste(val content: String, val html: String?)

Ver fichero

@ -0,0 +1,32 @@
package moe.kageru.kodeshare
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.logging.FileHandler
import java.util.logging.Formatter
import java.util.logging.LogRecord
import java.util.logging.Logger
object Log {
private val log: Logger by lazy {
val log = Logger.getGlobal()
val fh = FileHandler("kodeshare.log", true)
val formatter = LogFormatter()
fh.formatter = formatter
log.addHandler(fh)
return@lazy log
}
fun info(message: String) {
log.info(message)
}
}
private class LogFormatter : Formatter() {
private val timeFormatter: DateTimeFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault())
override fun format(record: LogRecord): String {
return "[${record.level}] ${timeFormatter.format(record.instant)}: ${record.message}\n"
}
}

Ver fichero

@ -0,0 +1,65 @@
package moe.kageru.kodeshare
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.content.PartData
import io.ktor.http.content.forEachPart
import io.ktor.http.content.streamProvider
import io.ktor.locations.Location
import io.ktor.locations.get
import io.ktor.request.receiveMultipart
import io.ktor.response.respond
import io.ktor.response.respondText
import io.ktor.routing.Routing
import io.ktor.routing.get
import io.ktor.routing.post
import moe.kageru.kodeshare.persistence.PasteDao
@ExperimentalStdlibApi
object Routes {
fun Routing.createRoutes() {
get("/") {
call.respondText("Hello, world!", ContentType.Text.Html)
}
post("/") {
save(call)
}
get<PasteRequest> { req ->
respondGet(call, req)
}
}
}
@ExperimentalStdlibApi
suspend fun save(call: ApplicationCall) {
call.receiveMultipart().forEachPart { part ->
when(part) {
is PartData.FileItem -> {
Log.info("new file")
val content = part.streamProvider().use { it.readAllBytes().decodeToString() }
val id = PasteDao.insert(Paste(content = content, html = null)).id
call.respond(HttpStatusCode.Created, "$id")
Log.info("Saving new paste with ID $id")
}
is PartData.FormItem -> {
Log.info("form item")
}
is PartData.BinaryItem -> {
Log.info("binary item")
}
}
}
}
suspend fun respondGet(call: ApplicationCall, req: PasteRequest) {
val id = req.id
Log.info("Retrieving paste $id")
PasteDao.select(id)?.data?.let { paste ->
call.respondText(paste.html ?: paste.content, ContentType.Text.Html)
} ?: call.respond(HttpStatusCode.NotFound, "nothing found for id $id")
}
@Location("/{id}")
data class PasteRequest(val id: Long)

Ver fichero

@ -0,0 +1,54 @@
package moe.kageru.kodeshare.persistence
import moe.kageru.kodeshare.Paste
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.mariadb.jdbc.MariaDbDataSource
object PasteDao {
fun select(id: Long): Transient<Paste>? = transaction {
PasteTable.select { PasteTable.id.eq(id) }.firstOrNull()
}?.toPaste()
fun insert(paste: Paste): Transient<Paste> = transaction {
val id = PasteTable.insert {
it[content] = paste.content
it[html] = paste.html
}[PasteTable.id]
Transient(id, paste)
}
init {
val source = MariaDbDataSource().apply {
userName = "kodepaste"
setPassword("12345")
databaseName = "kode"
}
Database.connect(source)
transaction {
SchemaUtils.drop(PasteTable)
SchemaUtils.create(PasteTable)
}
}
}
private fun ResultRow.toPaste() = Transient(
get(PasteTable.id),
Paste(
content = get(PasteTable.content),
html = get(PasteTable.html)
)
)
private object PasteTable : Table() {
val id = long("id").primaryKey().autoIncrement()
val content = text("content")
val html = text("html").nullable()
}
/*
* Better have that one generic class
* after deciding to make everything else
* not generic because it would be overkill
*/
data class Transient<DATA>(val id: Long, val data: DATA)