commit 03/09/2025

This commit is contained in:
2025-09-03 13:51:38 +07:00
parent ea04f8d316
commit ff4f0fd742
5 changed files with 508 additions and 105 deletions

View File

@@ -1,5 +1,6 @@
package codes package codes
import content.ScheduleDay
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@@ -23,6 +24,7 @@ class Somecodes {
val datetimeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss") val datetimeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")
val dateformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy") val dateformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
val timeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss") val timeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss")
val timeformat2: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm")
const val KB_threshold = 1024.0 const val KB_threshold = 1024.0
const val MB_threshold = KB_threshold * 1024.0 const val MB_threshold = KB_threshold * 1024.0
const val GB_threshold = MB_threshold * 1024.0 const val GB_threshold = MB_threshold * 1024.0
@@ -165,6 +167,52 @@ class Somecodes {
false false
} }
} }
/**
* Check if a string is a valid schedule time in the format "HH:mm".
* @param value The string to check.
* @return True if the string is a valid schedule time, false otherwise.
*/
fun ValidScheduleTime(value: String): Boolean{
// format HH:mm
try {
if (ValidString(value)){
timeformat2.parse(value)
return true
}
} catch (_ : Exception){
}
return false
}
/**
* Find a schedule day by its name.
* @param value The name of the schedule day to find.
* @return The name of the schedule day if found, null otherwise.
*/
fun FindScheduleDay(value: String) : String? {
val sd = ScheduleDay.entries.find { sd -> sd.name == value }
return sd?.name
}
/**
* Check if a string is a valid schedule day or a valid date.
* A valid schedule day is either one of the ScheduleDay enum names or a date in the format "dd/MM/yyyy".
* @param value The string to check.
* @return True if the string is a valid schedule day or date, false otherwise.
*/
fun ValidScheduleDay(value: String) : Boolean {
if (ValidString(value)){
// check if value is one of ScheduleDay enum name
if (FindScheduleDay(value) != null){
return true
}
// check if value is in format dd/MM/yyyy
return ValidDate(value)
}
return false
}
} }

View File

@@ -0,0 +1,13 @@
package content
@Suppress("unused")
enum class ScheduleDay(val day: String) {
Sunday("Sunday"),
Monday("Monday"),
Tuesday("Tuesday"),
Wednesday("Wednesday"),
Thursday("Thursday"),
Friday("Friday"),
Saturday("Saturday"),
Everyday("Everyday")
}

View File

@@ -1157,7 +1157,7 @@ class MariaDB(
* Exports the messagebank table to an XLSX workbook. * Exports the messagebank table to an XLSX workbook.
* @return An XSSFWorkbook containing the messagebank data. * @return An XSSFWorkbook containing the messagebank data.
*/ */
fun Export_Messagebank_XLSX(): XSSFWorkbook { fun Export_Messagebank_XLSX(): XSSFWorkbook? {
try { try {
val statement = connection?.createStatement() val statement = connection?.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM messagebank") val resultSet = statement?.executeQuery("SELECT * FROM messagebank")
@@ -1188,7 +1188,7 @@ class MariaDB(
} catch (e: Exception) { } catch (e: Exception) {
Logger.error { "Error exporting Messagebank, Msg: ${e.message}" } Logger.error { "Error exporting Messagebank, Msg: ${e.message}" }
} }
return XSSFWorkbook() return null
} }
fun Import_Messagebank_XLSX(workbook: XSSFWorkbook): Boolean { fun Import_Messagebank_XLSX(workbook: XSSFWorkbook): Boolean {

View File

@@ -1,4 +1,13 @@
package database package database
@Suppress("unused") @Suppress("unused")
data class ScheduleBank(var index: UInt, var Description: String, var Day: String, var Time: String, var Soundpath: String, var Repeat: UByte, var Enable: Boolean, var BroadcastZones: String, var Language: String) data class ScheduleBank(
var index: UInt,
var Description: String,
var Day: String,
var Time: String,
var Soundpath: String,
var Repeat: UByte,
var Enable: Boolean,
var BroadcastZones: String,
var Language: String)

View File

@@ -3,10 +3,14 @@ package web
import codes.Somecodes import codes.Somecodes
import codes.Somecodes.Companion.ValidDate import codes.Somecodes.Companion.ValidDate
import codes.Somecodes.Companion.ValidFile import codes.Somecodes.Companion.ValidFile
import codes.Somecodes.Companion.ValidScheduleDay
import codes.Somecodes.Companion.ValidScheduleTime
import codes.Somecodes.Companion.ValidString import codes.Somecodes.Companion.ValidString
import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import content.Category import content.Category
import content.Language
import content.VoiceType
import database.MariaDB import database.MariaDB
import database.Soundbank import database.Soundbank
import io.javalin.Javalin import io.javalin.Javalin
@@ -20,12 +24,13 @@ import io.javalin.apibuilder.ApiBuilder.ws
import io.javalin.http.Context import io.javalin.http.Context
import io.javalin.json.JavalinJackson import io.javalin.json.JavalinJackson
import io.javalin.websocket.WsMessageContext import io.javalin.websocket.WsMessageContext
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.time.LocalDateTime import java.time.LocalDateTime
@Suppress("unused") @Suppress("unused")
class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val db: MariaDB) { class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val db: MariaDB) {
var app : Javalin? = null var app: Javalin? = null
val objectmapper = jacksonObjectMapper() val objectmapper = jacksonObjectMapper()
private fun SendReply(context: WsMessageContext, command: String, value: String) { private fun SendReply(context: WsMessageContext, command: String, value: String) {
@@ -38,13 +43,12 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
fun Start() { fun Start() {
app = Javalin.create { app = Javalin.create { config ->
config ->
config.useVirtualThreads = true config.useVirtualThreads = true
config.staticFiles.add("/webpage") config.staticFiles.add("/webpage")
config.jsonMapper(JavalinJackson(jacksonObjectMapper())) config.jsonMapper(JavalinJackson(jacksonObjectMapper()))
config.router.apiBuilder { config.router.apiBuilder {
path("/"){ path("/") {
get { ctx -> get { ctx ->
// Serve the main page // Serve the main page
ctx.sessionAttribute("user", null) // Clear user session ctx.sessionAttribute("user", null) // Clear user session
@@ -52,8 +56,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
} }
path("login.html"){ path("login.html") {
post{ it -> post { it ->
// get username and password from form // get username and password from form
val username = it.formParam("username") val username = it.formParam("username")
val password = it.formParam("password") val password = it.formParam("password")
@@ -84,49 +88,78 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
println("WebSocket closed: ${wsCloseContext.session.remoteAddress}") println("WebSocket closed: ${wsCloseContext.session.remoteAddress}")
} }
ws.onMessage { wsMessageContext -> ws.onMessage { wsMessageContext ->
try{ try {
val cmd = objectmapper.readValue(wsMessageContext.message(), WebsocketCommand::class.java) val cmd =
objectmapper.readValue(wsMessageContext.message(), WebsocketCommand::class.java)
when (cmd.command) { when (cmd.command) {
"getSystemTime" ->{ "getSystemTime" -> {
SendReply(wsMessageContext, cmd.command, LocalDateTime.now().format(Somecodes.datetimeformat1)) SendReply(
wsMessageContext,
cmd.command,
LocalDateTime.now().format(Somecodes.datetimeformat1)
)
} }
"getCPUStatus" ->{
"getCPUStatus" -> {
Somecodes.getCPUUsage { vv -> Somecodes.getCPUUsage { vv ->
SendReply(wsMessageContext, cmd.command, vv ) SendReply(wsMessageContext, cmd.command, vv)
} }
} }
"getMemoryStatus" ->{
"getMemoryStatus" -> {
SendReply(wsMessageContext, cmd.command, Somecodes.getMemoryUsage()) SendReply(wsMessageContext, cmd.command, Somecodes.getMemoryUsage())
} }
"getDiskStatus" ->{
"getDiskStatus" -> {
SendReply(wsMessageContext, cmd.command, Somecodes.getDiskUsage()) SendReply(wsMessageContext, cmd.command, Somecodes.getDiskUsage())
} }
"getNetworkStatus" ->{
"getNetworkStatus" -> {
// TODO Get Network status // TODO Get Network status
SendReply(wsMessageContext, cmd.command, "OK") SendReply(wsMessageContext, cmd.command, "OK")
} }
"getSoundBankList" ->{
"getSoundBankList" -> {
println("getSoundBankList command received") println("getSoundBankList command received")
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.SoundbankList)) SendReply(
wsMessageContext,
cmd.command,
MariaDB.ArrayListtoString(db.SoundbankList)
)
} }
"getMessageBankList"->{
"getMessageBankList" -> {
println("getMessageBankList command received") println("getMessageBankList command received")
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.MessagebankList)) SendReply(
wsMessageContext,
cmd.command,
MariaDB.ArrayListtoString(db.MessagebankList)
)
} }
"getLanguageList"->{
"getLanguageList" -> {
println("getLanguageList command received") println("getLanguageList command received")
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.LanguageLinkList)) SendReply(
wsMessageContext,
cmd.command,
MariaDB.ArrayListtoString(db.LanguageLinkList)
)
} }
"getTimerList"->{
"getTimerList" -> {
println("getTimerList command received") println("getTimerList command received")
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.SchedulebankList)) SendReply(
wsMessageContext,
cmd.command,
MariaDB.ArrayListtoString(db.SchedulebankList)
)
} }
else -> { else -> {
SendReply(wsMessageContext, cmd.command, "Unknown command") SendReply(wsMessageContext, cmd.command, "Unknown command")
} }
} }
} catch (e: Exception){ } catch (e: Exception) {
println("Error processing WebSocket message: ${e.message}") println("Error processing WebSocket message: ${e.message}")
} }
@@ -139,7 +172,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
} }
path("soundbank.html") { path("soundbank.html") {
before {CheckUsers(it)} before { CheckUsers(it) }
} }
path("messagebank.html") { path("messagebank.html") {
before { CheckUsers(it) } before { CheckUsers(it) }
@@ -156,76 +189,79 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
path("timer.html") { path("timer.html") {
before { CheckUsers(it) } before { CheckUsers(it) }
} }
path("api"){ path("api") {
path("SoundBank"){ path("SoundBank") {
get("List"){ get("List") {
// get soundbank list // get soundbank list
it.result(MariaDB.ArrayListtoString(db.SoundbankList)) it.result(MariaDB.ArrayListtoString(db.SoundbankList))
} }
post("Add"){ post("Add") {
try { try {
val addvalue = objectmapper.readValue(it.body(), Soundbank::class.java) val addvalue = objectmapper.readValue(it.body(), Soundbank::class.java)
if (ValidString(addvalue.Description)){ if (ValidString(addvalue.Description)) {
if (ValidString(addvalue.TAG)){ if (ValidString(addvalue.TAG)) {
if (ValidString(addvalue.Category)){ if (ValidString(addvalue.Category)) {
if (ValidString(addvalue.Language)){ if (ValidString(addvalue.Language)) {
if (ValidString(addvalue.Path)){ if (ValidString(addvalue.Path)) {
// check apakah TAG sudah ada untuk language dan category yang sama // check apakah TAG sudah ada untuk language dan category yang sama
val exists = db.SoundbankList.any { sb -> val exists = db.SoundbankList.any { sb ->
sb.TAG == addvalue.TAG && sb.Language == addvalue.Language && sb.Category == addvalue.Category sb.TAG == addvalue.TAG && sb.Language == addvalue.Language && sb.Category == addvalue.Category
} }
if (!exists){ if (!exists) {
if (ValidFile(addvalue.Path)){ if (ValidFile(addvalue.Path)) {
if (db.Add_Soundbank(addvalue)){ if (db.Add_Soundbank(addvalue)) {
it.result("OK") it.result("OK")
} else it.status(500).result("Failed to add soundbank to database") } else it.status(500)
} else it.status(400).result("Invalid Path, file does not exist") .result("Failed to add soundbank to database")
} else it.status(400).result("TAG=${addvalue.TAG} already exists for the same Language=${addvalue.Language} and Category=${addvalue.Category}") } else it.status(400)
.result("Invalid Path, file does not exist")
} else it.status(400)
.result("TAG=${addvalue.TAG} already exists for the same Language=${addvalue.Language} and Category=${addvalue.Category}")
} else it.status(400).result("Invalid Path") } else it.status(400).result("Invalid Path")
} else it.status(400).result("Invalid Language") } else it.status(400).result("Invalid Language")
} else it.status(400).result("Invalid Category") } else it.status(400).result("Invalid Category")
} else it.status(400).result("Invalid TAG") } else it.status(400).result("Invalid TAG")
} else it.status(400).result("Invalid Description") } else it.status(400).result("Invalid Description")
} catch (_: Exception){ } catch (_: Exception) {
it.status(400).result("Invalid request body") it.status(400).result("Invalid request body")
} }
} }
delete("List"){ delete("List") {
// truncate soundbank table // truncate soundbank table
if (db.Clear_Soundbank()){ if (db.Clear_Soundbank()) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to truncate soundbank table") it.status(500).result("Failed to truncate soundbank table")
} }
} }
delete("DeleteByIndex/{index}"){ delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null){ if (index == null) {
it.status(400).result("Invalid index") it.status(400).result("Invalid index")
} else{ } else {
if (db.Delete_Soundbank_by_index(index)){ if (db.Delete_Soundbank_by_index(index)) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to delete soundbank with index $index") it.status(500).result("Failed to delete soundbank with index $index")
} }
} }
} }
patch("UpdateByIndex/{index}"){ patch("UpdateByIndex/{index}") {
// update by index // update by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null){ if (index == null) {
// tidak ada path param index // tidak ada path param index
it.status(400).result("Invalid index") it.status(400).result("Invalid index")
} else { } else {
val sb = db.SoundbankList.find{ xx -> xx.index == index } val sb = db.SoundbankList.find { xx -> xx.index == index }
if (sb == null){ if (sb == null) {
// soundbank dengan index tersebut tidak ditemukan // soundbank dengan index tersebut tidak ditemukan
it.status(404).result("Soundbank with index $index not found") it.status(404).result("Soundbank with index $index not found")
} else { } else {
// soundbank dengan index tersebut ditemukan, sekarang update // soundbank dengan index tersebut ditemukan, sekarang update
val json : JsonNode = objectmapper.readTree(it.body()) val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty){ if (json.isEmpty) {
it.status(400).result("UpdateByIndex with index=$index has empty body") it.status(400).result("UpdateByIndex with index=$index has empty body")
} else { } else {
val _description = json.get("Description").asText() val _description = json.get("Description").asText()
@@ -234,17 +270,17 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val _language = json.get("Language").asText() val _language = json.get("Language").asText()
val _path = json.get("Path").asText() val _path = json.get("Path").asText()
var changed = false var changed = false
if (ValidString(_description) && _description!=sb.Description){ if (ValidString(_description) && _description != sb.Description) {
sb.Description = _description sb.Description = _description
changed = true changed = true
} }
if (ValidString(_tag) && _tag!=sb.TAG){ if (ValidString(_tag) && _tag != sb.TAG) {
sb.TAG = _tag sb.TAG = _tag
changed = true changed = true
} }
if (ValidString(_category) && _category!=sb.Category){ if (ValidString(_category) && _category != sb.Category) {
if (Category.entries.any { if (Category.entries.any { cat ->
cat -> cat.name == _category cat.name == _category
}) { }) {
sb.Category = _category sb.Category = _category
changed = true changed = true
@@ -253,12 +289,12 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
return@patch return@patch
} }
} }
if (ValidString(_language) && _language!=sb.Language){ if (ValidString(_language) && _language != sb.Language) {
sb.Language = _language sb.Language = _language
changed = true changed = true
} }
if (ValidString(_path) && _path!=sb.Path){ if (ValidString(_path) && _path != sb.Path) {
if (ValidFile(_path)){ if (ValidFile(_path)) {
sb.Path = _path sb.Path = _path
changed = true changed = true
} else { } else {
@@ -266,119 +302,417 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
return@patch return@patch
} }
} }
if (changed){ if (changed) {
if (db.Update_Soundbank_by_index(index, sb)){ if (db.Update_Soundbank_by_index(index, sb)) {
it.result("OK") it.result("OK")
} else it.status(500).result("Failed to update soundbank with index $index") } else it.status(500).result("Failed to update soundbank with index $index")
} else it.status(400).result("Nothing has changed for soundbank with index $index") } else it.status(400)
.result("Nothing has changed for soundbank with index $index")
} }
} }
} }
} }
get("ExportXLSX"){ get("ExportXLSX") {
val xlsxdata = db.Export_Soundbank_XLSX()
if (xlsxdata != null) {
it.header(
"Content-Type",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
it.header("Content-Disposition", "attachment; filename=\"soundbank.xlsx\"")
it.outputStream().use { out ->
xlsxdata.write(out)
} }
post("ImportXLSX"){ } else {
it.status(500).result("Failed to export soundbank to XLSX")
}
}
post("ImportXLSX") {
val uploaded = it.uploadedFile("file") val uploaded = it.uploadedFile("file")
if (uploaded==null){ if (uploaded == null) {
it.status(400).result("No file uploaded") it.status(400).result("No file uploaded")
return@post return@post
} }
try {
val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_Soundbank_XLSX(xlsx)) {
it.result("OK")
} else {
it.status(500).result("Failed to import soundbank from XLSX")
}
} catch (e: Exception) {
it.status(400).result("Invalid XLSX file")
} }
} }
path("MessageBank"){ }
get("List"){ path("MessageBank") {
get("List") {
// get messagebank list // get messagebank list
it.result(MariaDB.ArrayListtoString(db.MessagebankList)) it.result(MariaDB.ArrayListtoString(db.MessagebankList))
} }
delete("List"){ delete("List") {
// truncate messagebank table // truncate messagebank table
if (db.Clear_Messagebank()){ if (db.Clear_Messagebank()) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to truncate messagebank table") it.status(500).result("Failed to truncate messagebank table")
} }
} }
delete("DeleteByIndex/{index}"){ delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null){ if (index == null) {
it.status(400).result("Invalid index") it.status(400).result("Invalid index")
} else{ } else {
if (db.Delete_Messagebank_by_index(index)){ if (db.Delete_Messagebank_by_index(index)) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to delete messagebank with index $index") it.status(500).result("Failed to delete messagebank with index $index")
} }
} }
} }
patch("UpdateByIndex/{index}") {
// update messagebank by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result("Invalid index")
} else {
val mb = db.MessagebankList.find { xx -> xx.index == index }
if (mb == null) {
it.status(404).result("Messagebank with index $index not found")
} else {
val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty) {
it.status(400).result("UpdateByIndex with index=$index has empty body")
} else {
val _description = json.get("Description").asText()
val _language = json.get("Language").asText()
val _ann_id = json.get("ANN_ID").asInt().toUInt()
val _voice_type = json.get("Voice_Type").asText()
val _message_detail = json.get("Message_Detail").asText()
val _message_tags = json.get("Message_TAGS").asText()
var changed = false
if (ValidString(_description) && _description != mb.Description) {
mb.Description = _description
changed = true
} }
path("LanguageLink"){ if (ValidString(_language) && _language != mb.Language) {
get("List"){ mb.Language = _language
changed = true
}
if (_ann_id > 0u && _ann_id != mb.ANN_ID) {
mb.ANN_ID = _ann_id
changed = true
}
if (ValidString(_voice_type) && _voice_type != mb.Voice_Type) {
if (VoiceType.entries.any { vt -> vt.name == _voice_type }) {
mb.Voice_Type = _voice_type
changed = true
} else {
it.status(400).result("Invalid Voice_Type")
return@patch
}
}
if (ValidString(_message_detail) && _message_detail != mb.Message_Detail) {
mb.Message_Detail = _message_detail
changed = true
}
if (ValidString(_message_tags) && _message_tags != mb.Message_TAGS) {
mb.Message_TAGS = _message_tags
changed = true
}
if (changed) {
if (db.Update_Messagebank_by_index(index, mb)) {
it.result("OK")
} else it.status(500)
.result("Failed to update messagebank with index $index")
} else it.status(400)
.result("Nothing has changed for messagebank with index $index")
}
}
}
}
get("ExportXLSX") {
val xlsxdata = db.Export_Messagebank_XLSX()
if (xlsxdata != null) {
it.header(
"Content-Type",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
it.header("Content-Disposition", "attachment; filename=\"messagebank.xlsx\"")
it.outputStream().use { out ->
xlsxdata.write(out)
}
} else {
it.status(500).result("Failed to export messagebank to XLSX")
}
}
post("ImportXLSX") {
val uploaded = it.uploadedFile("file")
if (uploaded == null) {
it.status(400).result("No file uploaded")
return@post
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_Messagebank_XLSX(xlsx)) {
it.result("OK")
} else {
it.status(500).result("Failed to import messagebank from XLSX")
}
} catch (e: Exception) {
it.status(400).result("Invalid XLSX file")
}
}
}
path("LanguageLink") {
get("List") {
// get language link list // get language link list
it.result(MariaDB.ArrayListtoString(db.LanguageLinkList)) it.result(MariaDB.ArrayListtoString(db.LanguageLinkList))
} }
delete("List"){ delete("List") {
// truncate language link table // truncate language link table
if (db.Clear_LanguageLink()){ if (db.Clear_LanguageLink()) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to truncate language link table") it.status(500).result("Failed to truncate language link table")
} }
} }
delete("DeleteByIndex/{index}"){ delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null){ if (index == null) {
it.status(400).result("Invalid index") it.status(400).result("Invalid index")
} else{ } else {
if (db.Delete_LanguageLink_by_index(index)){ if (db.Delete_LanguageLink_by_index(index)) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to delete language link with index $index") it.status(500).result("Failed to delete language link with index $index")
} }
} }
} }
patch("UpdateByIndex/{index}") {
// update by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result("Invalid index")
} else {
val ll = db.LanguageLinkList.find { xx -> xx.index == index }
if (ll == null) {
it.status(404).result("Language link with index $index not found")
} else {
val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty) {
it.status(400).result("UpdateByIndex with index=$index has empty body")
} else {
val _tag = json.get("TAG").asText()
val _language = json.get("Language").asText()
var changed = false
if (ValidString(_language) && _language != ll.Language) {
ll.Language = _language
changed = true
} }
path("ScheduleBank"){ if (ValidString(_tag) && _tag != ll.TAG) {
get("List"){ ll.TAG = _tag
changed = true
}
if (changed) {
if (db.Update_LanguageLink_by_index(index, ll)) {
it.result("OK")
} else it.status(500)
.result("Failed to update language link with index $index")
} else it.status(400)
.result("Nothing has changed for language link with index $index")
}
}
}
}
get("ExportXLSX") {
val xlsxdata = db.Export_LanguageLink_XLSX()
if (xlsxdata != null) {
it.header(
"Content-Type",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
it.header("Content-Disposition", "attachment; filename=\"languagelink.xlsx\"")
it.outputStream().use { out ->
xlsxdata.write(out)
}
} else {
it.status(500).result("Failed to export language link to XLSX")
}
}
post("ImportXLSX") {
val uploaded = it.uploadedFile("file")
if (uploaded == null) {
it.status(400).result("No file uploaded")
return@post
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_LanguageLink_XLSX(xlsx)) {
it.result("OK")
} else {
it.status(500).result("Failed to import language link from XLSX")
}
} catch (e: Exception) {
it.status(400).result("Invalid XLSX file")
}
}
}
path("ScheduleBank") {
get("List") {
// get timer list // get timer list
it.result(MariaDB.ArrayListtoString(db.SchedulebankList)) it.result(MariaDB.ArrayListtoString(db.SchedulebankList))
} }
delete("List"){ delete("List") {
// truncate timer table // truncate timer table
if (db.Clear_Schedulebank()){ if (db.Clear_Schedulebank()) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to truncate schedulebank table") it.status(500).result("Failed to truncate schedulebank table")
} }
} }
delete("DeleteByIndex/{index}"){ delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null){ if (index == null) {
it.status(400).result("Invalid index") it.status(400).result("Invalid index")
} else{ } else {
if (db.Delete_Schedulebank_by_index(index)){ if (db.Delete_Schedulebank_by_index(index)) {
it.result("OK") it.result("OK")
} else { } else {
it.status(500).result("Failed to delete schedule with index $index") it.status(500).result("Failed to delete schedule with index $index")
} }
} }
} }
patch("UpdateByIndex/{index}") {
// update by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result("Invalid index")
} else {
val sb = db.SchedulebankList.find { xx -> xx.index == index }
if (sb == null) {
it.status(404).result("Schedule with index $index not found")
} else {
val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty) {
it.status(400).result("UpdateByIndex with index=$index has empty body")
} else {
val _description = json.get("Description").asText()
val _time = json.get("Time").asText()
val _day = json.get("Day").asText()
val _soundpath = json.get("Soundpath").asText()
val _repeat = json.get("Repeat").asInt().toUByte()
val _enable = json.get("Enable").asBoolean()
val _broadcast_zones = json.get("BroadcastZones").asText()
val _language = json.get("Language").asText()
var changed = false
if (ValidString(_description) && _description != sb.Description) {
sb.Description = _description
changed = true
} }
path("Log"){ if (ValidString(_time) && _time != sb.Time) {
get("List/<logdate>/<logfilter>"){ get1 -> if (ValidScheduleTime(_time)) {
sb.Time = _time
changed = true
} else {
it.status(400).result("Invalid Time format, must be HH:mm")
return@patch
}
}
if (ValidString(_day) && _day != sb.Day) {
if (ValidScheduleDay(_day)) {
sb.Day = _day
changed = true
} else {
it.status(400).result("Invalid Day format")
return@patch
}
}
if (ValidString(_soundpath) && _soundpath != sb.Soundpath) {
sb.Soundpath = _soundpath
changed = true
}
if (_repeat != sb.Repeat) {
sb.Repeat = _repeat
changed = true
}
if (_enable != sb.Enable) {
sb.Enable = _enable
changed = true
}
if (ValidString(_broadcast_zones) && _broadcast_zones != sb.BroadcastZones) {
sb.BroadcastZones = _broadcast_zones
changed = true
}
if (ValidString(_language) && _language != sb.Language) {
if (Language.entries.any{ lang -> lang.name == _language }) {
sb.Language = _language
changed = true
} else {
it.status(400).result("Invalid Language")
return@patch
}
}
if (changed) {
if (db.Update_Schedulebank_by_index(index, sb)) {
it.result("OK")
} else it.status(500)
.result("Failed to update schedule with index $index")
} else it.status(400)
.result("Nothing has changed for schedule with index $index")
}
}
}
}
get("ExportXLSX") {
val xlsxdata = db.Export_Schedulebank_XLSX()
if (xlsxdata != null) {
it.header(
"Content-Type",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
it.header("Content-Disposition", "attachment; filename=\"schedulebank.xlsx\"")
it.outputStream().use { out ->
xlsxdata.write(out)
}
} else {
it.status(500).result("Failed to export schedulebank to XLSX")
}
}
post("ImportXLSX") {
val uploaded = it.uploadedFile("file")
if (uploaded == null) {
it.status(400).result("No file uploaded")
return@post
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_Schedulebank_XLSX(xlsx)) {
it.result("OK")
} else {
it.status(500).result("Failed to import schedulebank from XLSX")
}
} catch (e: Exception) {
it.status(400).result("Invalid XLSX file")
}
}
}
path("Log") {
get("List/<logdate>/<logfilter>") { get1 ->
val logdate = get1.pathParam("logdate") val logdate = get1.pathParam("logdate")
val logfilter = get1.pathParam("logfilter") val logfilter = get1.pathParam("logfilter")
if (ValidDate(logdate)){ if (ValidDate(logdate)) {
if (ValidString(logfilter)){ if (ValidString(logfilter)) {
// ada log filter // ada log filter
db.GetLog(logdate, logfilter){ db.GetLog(logdate, logfilter) {
get1.result(MariaDB.ArrayListtoString(it)) get1.result(MariaDB.ArrayListtoString(it))
} }
} else { } else {
db.GetLog(logdate){ db.GetLog(logdate) {
get1.result(MariaDB.ArrayListtoString(it)) get1.result(MariaDB.ArrayListtoString(it))
} }
} }
@@ -392,19 +726,18 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
fun CheckUsers(ctx: Context) {
fun CheckUsers(ctx: Context){
val user = ctx.sessionAttribute<String?>("user") val user = ctx.sessionAttribute<String?>("user")
if (user == null) { if (user == null) {
ctx.redirect("login.html") ctx.redirect("login.html")
} }
val foundUser = userlist.find { it.first == user } val foundUser = userlist.find { it.first == user }
if (foundUser==null) { if (foundUser == null) {
ctx.redirect("login.html") ctx.redirect("login.html")
} }
} }
fun Stop(){ fun Stop() {
app?.stop() app?.stop()
} }