forked from openrs2/openrs2
parent
6e9ba80d0c
commit
47127113f4
@ -0,0 +1,41 @@ |
|||||||
|
package org.openrs2.archive.web |
||||||
|
|
||||||
|
import io.ktor.application.ApplicationCall |
||||||
|
import io.ktor.http.ContentType |
||||||
|
import io.ktor.http.HttpStatusCode |
||||||
|
import io.ktor.response.header |
||||||
|
import io.ktor.response.respond |
||||||
|
import io.ktor.response.respondOutputStream |
||||||
|
import io.ktor.thymeleaf.ThymeleafContent |
||||||
|
import io.netty.buffer.ByteBufAllocator |
||||||
|
import org.openrs2.archive.cache.CacheExporter |
||||||
|
import org.openrs2.cache.DiskStoreZipWriter |
||||||
|
import java.util.zip.ZipOutputStream |
||||||
|
import javax.inject.Inject |
||||||
|
import javax.inject.Singleton |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public class CachesController @Inject constructor( |
||||||
|
private val exporter: CacheExporter, |
||||||
|
private val alloc: ByteBufAllocator |
||||||
|
) { |
||||||
|
public suspend fun index(call: ApplicationCall) { |
||||||
|
val caches = exporter.list() |
||||||
|
call.respond(ThymeleafContent("caches/index.html", mapOf("caches" to caches))) |
||||||
|
} |
||||||
|
|
||||||
|
public suspend fun export(call: ApplicationCall) { |
||||||
|
val id = call.parameters["id"]?.toLongOrNull() |
||||||
|
if (id == null) { |
||||||
|
call.respond(HttpStatusCode.NotFound) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
call.response.header("Content-Disposition", "attachment; filename=\"cache.zip\"") |
||||||
|
call.respondOutputStream(contentType = ContentType.Application.Zip) { |
||||||
|
DiskStoreZipWriter(ZipOutputStream(this), alloc = alloc).use { store -> |
||||||
|
exporter.export(id, store) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
package org.openrs2.archive.web |
||||||
|
|
||||||
|
import io.ktor.application.ApplicationCall |
||||||
|
import io.ktor.http.HttpStatusCode |
||||||
|
import io.ktor.response.respond |
||||||
|
import org.openrs2.archive.key.KeyImporter |
||||||
|
import org.openrs2.crypto.XteaKey |
||||||
|
import javax.inject.Inject |
||||||
|
import javax.inject.Singleton |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public class KeysController @Inject constructor( |
||||||
|
private val importer: KeyImporter |
||||||
|
) { |
||||||
|
public suspend fun create(call: ApplicationCall) { |
||||||
|
val k0 = call.request.queryParameters["key1"]?.toIntOrNull() |
||||||
|
val k1 = call.request.queryParameters["key2"]?.toIntOrNull() |
||||||
|
val k2 = call.request.queryParameters["key3"]?.toIntOrNull() |
||||||
|
val k3 = call.request.queryParameters["key4"]?.toIntOrNull() |
||||||
|
|
||||||
|
if (k0 == null || k1 == null || k2 == null || k3 == null) { |
||||||
|
call.respond(HttpStatusCode.BadRequest) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
importer.import(listOf(XteaKey(k0, k1, k2, k3))) |
||||||
|
call.respond(HttpStatusCode.NoContent) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package org.openrs2.archive.web |
||||||
|
|
||||||
|
import com.github.ajalt.clikt.core.CliktCommand |
||||||
|
import com.google.inject.Guice |
||||||
|
import org.openrs2.archive.ArchiveModule |
||||||
|
|
||||||
|
public class WebCommand : CliktCommand(name = "web") { |
||||||
|
override fun run() { |
||||||
|
val injector = Guice.createInjector(ArchiveModule) |
||||||
|
val server = injector.getInstance(WebServer::class.java) |
||||||
|
server.start() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package org.openrs2.archive.web |
||||||
|
|
||||||
|
import io.ktor.application.call |
||||||
|
import io.ktor.application.install |
||||||
|
import io.ktor.routing.get |
||||||
|
import io.ktor.routing.routing |
||||||
|
import io.ktor.server.engine.embeddedServer |
||||||
|
import io.ktor.server.netty.Netty |
||||||
|
import io.ktor.thymeleaf.Thymeleaf |
||||||
|
import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect |
||||||
|
import org.thymeleaf.templatemode.TemplateMode |
||||||
|
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver |
||||||
|
import javax.inject.Inject |
||||||
|
import javax.inject.Singleton |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public class WebServer @Inject constructor( |
||||||
|
private val cachesController: CachesController, |
||||||
|
private val keysController: KeysController |
||||||
|
) { |
||||||
|
public fun start() { |
||||||
|
embeddedServer(Netty, port = 8000) { |
||||||
|
install(Thymeleaf) { |
||||||
|
addDialect(Java8TimeDialect()) |
||||||
|
|
||||||
|
setTemplateResolver(ClassLoaderTemplateResolver().apply { |
||||||
|
prefix = "/org/openrs2/archive/templates/" |
||||||
|
templateMode = TemplateMode.HTML |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
routing { |
||||||
|
get("/caches") { cachesController.index(call) } |
||||||
|
get("/caches/{id}.zip") { cachesController.export(call) } |
||||||
|
|
||||||
|
// ideally we'd use POST /keys here, but I want to be compatible with the RuneLite/OpenOSRS API |
||||||
|
get("/keys/submit") { keysController.create(call) } |
||||||
|
} |
||||||
|
}.start(wait = true) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html xmlns:th="http://www.thymeleaf.org" lang="en"> |
||||||
|
<body> |
||||||
|
<table> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th>Master Index Digest</th> |
||||||
|
<th>Game</th> |
||||||
|
<th>Build</th> |
||||||
|
<th>Timestamp</th> |
||||||
|
<th></th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<!--/*@thymesVar id="caches" type="java.util.List<org.openrs2.archive.cache.CacheExporter.Cache>"*/--> |
||||||
|
<tr th:each="cache : ${caches}"> |
||||||
|
<td th:text="${@io.netty.buffer.ByteBufUtil@hexDump(cache.whirlpool).substring(0, 8)}">00000000</td> |
||||||
|
<td th:text="${cache.game}">runescape</td> |
||||||
|
<td th:text="${cache.build}">550</td> |
||||||
|
<td th:text="${#temporals.formatISO(cache.timestamp)}"></td> |
||||||
|
<td> |
||||||
|
<a th:href="${'/caches/' + cache.id + '.zip'}">Download</a> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</body> |
||||||
|
</html> |
||||||
|
|
Loading…
Reference in new issue