Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ dependencies {
implementation("io.ktor:ktor-server-host-common-jvm:$ktor_version")
implementation("io.ktor:ktor-server-status-pages-jvm:$ktor_version")
implementation("io.ktor:ktor-server-webjars-jvm:$ktor_version")
implementation("org.webjars:jquery:3.6.1")
implementation("io.ktor:ktor-server-sessions:$ktor_version")
implementation("io.ktor:ktor-server-mustache:$ktor_version")
implementation("io.ktor:ktor-server-metrics-micrometer-jvm:$ktor_version")
implementation("io.micrometer:micrometer-registry-prometheus:$prometeus_version")
Expand All @@ -48,3 +48,8 @@ dependencies {
testImplementation("it.skrape:skrapeit-core:+")
testImplementation("it.skrape:skrapeit-ktor:+")
}

tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar").configure {
minimize()
archiveClassifier.set("")
}
20 changes: 14 additions & 6 deletions src/main/kotlin/name/denyago/Application.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package name.denyago // ktlint-disable filename

import com.lordcodes.turtle.ShellScript
import io.ktor.server.application.* // ktlint-disable no-wildcard-imports
import io.ktor.server.engine.* // ktlint-disable no-wildcard-imports
import io.ktor.server.netty.* // ktlint-disable no-wildcard-imports
import io.ktor.server.sessions.* // ktlint-disable no-wildcard-imports
import name.denyago.volumes.MontedVolumes
import name.denyago.volumes.http.volumesApi
import name.denyago.web.HttpSession
import name.denyago.web.startPage
import name.denyago.web.staticResources
import org.kodein.di.DI
Expand All @@ -12,13 +16,17 @@ import org.kodein.di.instance
import org.kodein.di.singleton

fun main() {
val di = DI {
bind<ShellScript>() with singleton { ShellScript() }
bind<MontedVolumes>() with singleton { MontedVolumes(instance()) }
}
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
install(Sessions) {
cookie<HttpSession>("the_session")
}

staticResources()
startPage(
DI {
bind<ShellScript>() with singleton { ShellScript() }
bind<MontedVolumes>() with singleton { MontedVolumes(instance()) }
}
)
startPage(di)
volumesApi(di)
}.start(wait = true)
}
2 changes: 1 addition & 1 deletion src/main/kotlin/name/denyago/volumes/DriveState.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package name.denyago.volumes

data class DriveState(val mountPoint: String, val connected: Boolean)
data class DriveState(val mountPoint: MountPoint, val connected: Boolean)
14 changes: 12 additions & 2 deletions src/main/kotlin/name/denyago/volumes/MontedVolumes.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package name.denyago.volumes

import com.lordcodes.turtle.ShellRunException
import com.lordcodes.turtle.ShellScript

class MontedVolumes(private val shell: ShellScript) {

fun statuses(mountPoints: List<String>): List<DriveState> {
fun statuses(mountPoints: List<MountPoint>): List<DriveState> {
val allMounts = shell.command("mount")
return mountPoints.map { mountPoint ->
DriveState(mountPoint, allMounts.contains(mountPoint))
DriveState(mountPoint, allMounts.contains(mountPoint.toString()))
}
}

fun mount(mountPoint: MountPoint): Result<MountPoint> {
try {
shell.command("ls", listOf("/foo"))
} catch (e: ShellRunException) {
return Result.failure(e)
}
return Result.success(mountPoint)
}
}
4 changes: 4 additions & 0 deletions src/main/kotlin/name/denyago/volumes/MountPoint.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package name.denyago.volumes

@JvmInline
value class MountPoint(val path: String)
26 changes: 26 additions & 0 deletions src/main/kotlin/name/denyago/volumes/http/Api.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package name.denyago.volumes.http // ktlint-disable filename

import io.ktor.server.application.* // ktlint-disable no-wildcard-imports
import io.ktor.server.request.* // ktlint-disable no-wildcard-imports
import io.ktor.server.response.* // ktlint-disable no-wildcard-imports
import io.ktor.server.routing.* // ktlint-disable no-wildcard-imports
import io.ktor.server.sessions.* // ktlint-disable no-wildcard-imports
import name.denyago.volumes.MontedVolumes
import name.denyago.web.HttpSession
import org.kodein.di.DI
import org.kodein.di.instance

fun Application.volumesApi(kodein: DI) {
routing {
val mountedVolumes by kodein.instance<MontedVolumes>()

post("/mount") {
val mountRequest = call.receive<MountRequest>()
val result = mountedVolumes.mount(mountRequest.mountPoint)
if (result.isFailure) {
call.sessions.set(HttpSession(result.exceptionOrNull().toString()))
}
call.respondRedirect("/")
}
}
}
5 changes: 5 additions & 0 deletions src/main/kotlin/name/denyago/volumes/http/MountRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package name.denyago.volumes.http

import name.denyago.volumes.MountPoint

data class MountRequest(val mountPoint: MountPoint)
3 changes: 3 additions & 0 deletions src/main/kotlin/name/denyago/web/HttpSession.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package name.denyago.web

data class HttpSession(val error: String?)
13 changes: 9 additions & 4 deletions src/main/kotlin/name/denyago/web/StartPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import io.ktor.server.application.* // ktlint-disable no-wildcard-imports
import io.ktor.server.mustache.* // ktlint-disable no-wildcard-imports
import io.ktor.server.response.* // ktlint-disable no-wildcard-imports
import io.ktor.server.routing.* // ktlint-disable no-wildcard-imports
import io.ktor.server.sessions.* // ktlint-disable no-wildcard-imports
import name.denyago.volumes.DriveState
import name.denyago.volumes.MontedVolumes
import name.denyago.volumes.MountPoint
import org.kodein.di.DI
import org.kodein.di.instance

Expand All @@ -19,16 +21,19 @@ fun Application.startPage(kodein: DI) {

routing {
get("/") {
val driveStates = mountedVolumes.statuses(listOf("/mnt/Photos", "/mnt/Docs", "/mnt/Movies"))
val driveStates = mountedVolumes.statuses(
listOf("/mnt/Photos", "/mnt/Docs", "/mnt/Movies").map { MountPoint(it) }
)
val page = IndexPage(
hddState = HddState(driveStates.any { it.connected }), // HddState(busy = true),
hddState = HddState(driveStates.any { it.connected }),
driveStates = driveStates,
lastDriveError = "Non-root can't mount volumes."
lastDriveError = call.sessions.get<HttpSession>()?.error
)
call.sessions.clear<HttpSession>()
call.respond(MustacheContent("index.hbs", page))
}
}
}

data class HddState(val busy: Boolean)
data class IndexPage(val hddState: HddState, val driveStates: List<DriveState>, val lastDriveError: String)
data class IndexPage(val hddState: HddState, val driveStates: List<DriveState>, val lastDriveError: String?)
2 changes: 1 addition & 1 deletion src/main/resources/templates/index/connectedDrivesTile.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<span class="icon">
<i class="mdi mdi-folder"></i>
</span>
<span>{{ mountPoint }}</span>
<span>{{ mountPoint.path }}</span>
</td>
<td>
{{#connected}}
Expand Down