package web import StreamerOutputs import codes.Somecodes import codes.Somecodes.Companion.ListAudioFiles import codes.Somecodes.Companion.ValiDateForLogHtml import codes.Somecodes.Companion.ValidFile import codes.Somecodes.Companion.ValidIPV4 import codes.Somecodes.Companion.ValidScheduleDay import codes.Somecodes.Companion.ValidScheduleTime import codes.Somecodes.Companion.ValidString import codes.Somecodes.Companion.ValidStrings import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import content.Category import content.Language import content.ScheduleDay import content.VoiceType import database.BroadcastZones import database.LanguageLink import database.MariaDB import database.Messagebank import database.ScheduleBank import database.SoundChannel import database.Soundbank import database.UserDB import db import io.javalin.Javalin import io.javalin.apibuilder.ApiBuilder.before import io.javalin.apibuilder.ApiBuilder.delete import io.javalin.apibuilder.ApiBuilder.get import io.javalin.apibuilder.ApiBuilder.patch import io.javalin.apibuilder.ApiBuilder.path import io.javalin.apibuilder.ApiBuilder.post import io.javalin.apibuilder.ApiBuilder.ws import io.javalin.http.Context import io.javalin.json.JavalinJackson import io.javalin.websocket.WsMessageContext import org.apache.poi.xssf.usermodel.XSSFWorkbook import java.nio.file.Files import java.time.LocalDateTime @Suppress("unused") class WebApp(val listenPort: Int, val userlist: List>) { var app: Javalin? = null val objectmapper = jacksonObjectMapper() private fun SendReply(context: WsMessageContext, command: String, value: String) { try { if (context.session.isOpen) { context.send(objectmapper.writeValueAsString(WebsocketReply(command, value))) } } catch (_: Exception) { } } fun Start() { app = Javalin.create { config -> config.useVirtualThreads = true config.staticFiles.add("/webpage") config.jsonMapper(JavalinJackson(jacksonObjectMapper())) config.router.apiBuilder { path("/") { get { ctx -> // Serve the main page ctx.sessionAttribute("user", null) // Clear user session ctx.redirect("login.html") } } path("login.html") { post { it -> // get username and password from form val username = it.formParam("username") val password = it.formParam("password") if (username == null || password == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Username and password are required"))) return@post } // Check if user exists in userlist val user = userlist.find { it.first == username && it.second == password } if (user == null) { it.status(401).result(objectmapper.writeValueAsString(resultMessage("Invalid username or password"))) return@post } // Set user session it.sessionAttribute("user", user.first) println("User ${user.first} logged in") // Redirect to home page it.redirect("home.html") } } path("home.html") { before { CheckUsers(it) } ws("/ws") { ws -> // WebSocket endpoint for home ws.onClose { wsCloseContext -> // TODO Handle WebSocket close event println("WebSocket closed: ${wsCloseContext.session.remoteAddress}") } ws.onMessage { wsMessageContext -> try { val cmd = objectmapper.readValue(wsMessageContext.message(), WebsocketCommand::class.java) when (cmd.command) { "getSystemTime" -> { SendReply( wsMessageContext, cmd.command, LocalDateTime.now().format(Somecodes.datetimeformat1) ) } "getCPUStatus" -> { Somecodes.getCPUUsage { vv -> SendReply(wsMessageContext, cmd.command, vv) } } "getMemoryStatus" -> { SendReply(wsMessageContext, cmd.command, Somecodes.getMemoryUsage()) } "getDiskStatus" -> { SendReply(wsMessageContext, cmd.command, Somecodes.getDiskUsage()) } "getNetworkStatus" -> { // TODO Get Network status Somecodes.GetNetworkStatus("") SendReply(wsMessageContext, cmd.command, "OK") } "getPagingQueue" ->{ SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(db.queuepagingDB.List)) } "getAASQueue" ->{ SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(db.queuetableDB.List)) } "getStreamerOutputs" -> { SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(StreamerOutputs.values.toList())) } else -> { SendReply(wsMessageContext, cmd.command, "Unknown command") } } } catch (e: Exception) { println("Error processing WebSocket message: ${e.message}") } } ws.onConnect { wsConnectContext -> // TODO Handle WebSocket connect event println("WebSocket connected: ${wsConnectContext.session.remoteAddress}") } } } path("soundbank.html") { before { CheckUsers(it) } } path("messagebank.html") { before { CheckUsers(it) } } path("language.html") { before { CheckUsers(it) } } path("log.html") { before { CheckUsers(it) } } path("setting.html") { before { CheckUsers(it) } } path("timer.html") { before { CheckUsers(it) } } path("api") { path("VoiceType"){ get{ it.result(objectmapper.writeValueAsString(VoiceType.entries.map { vt -> vt.name })) } } path("Category") { get { it.result(objectmapper.writeValueAsString(Category.entries.map { cat -> cat.name}) ) } } path("Language") { get { it.result(objectmapper.writeValueAsString(Language.entries.map { lang -> lang.name }) ) } } path("ScheduleDay") { get { it.result(objectmapper.writeValueAsString(ScheduleDay.entries.map { day -> day.toString() })) } } path("ListFiles/{Language}/{VoiceType}/{Category}") { get { ctx -> val language = ctx.pathParam("Language") val voiceType = ctx.pathParam("VoiceType") val category = ctx.pathParam("Category") if (ValidString(language) && Language.entries.any { lang -> lang.name == language }) { if (ValidString(voiceType) && VoiceType.entries.any { vt -> vt.name == voiceType }) { if (ValidString(category) && Category.entries.any { cat -> cat.name == category }) { val dir = Somecodes.SoundbankDirectory( Language.valueOf(language), VoiceType.valueOf(voiceType), Category.valueOf(category) ) if (Files.isDirectory(dir)){ val list = ListAudioFiles(dir) ctx.result(objectmapper.writeValueAsString(list)) } else ctx.status(400) .result(objectmapper.writeValueAsString(resultMessage("Directory does not exist"))) } else ctx.status(400) .result(objectmapper.writeValueAsString(resultMessage("Invalid Category"))) } else ctx.status(400) .result(objectmapper.writeValueAsString(resultMessage("Invalid VoiceType"))) } else ctx.status(400) .result(objectmapper.writeValueAsString(resultMessage("Invalid Language"))) } } path("SoundBank") { get("List") { it.result(MariaDB.ArrayListtoString(db.soundDB.List)) } get("ListFiles") { it.result(objectmapper.writeValueAsString(ListAudioFiles(Somecodes.Soundbank_directory))) } get("AirlineTags") { ctx -> val value = db.soundDB.List .filter { it.Category == Category.Airplane_Name.name } .distinctBy { it.TAG } .sortedBy { it.TAG } .map { KeyValueMessage(it.TAG, it.Description) } ctx.result(objectmapper.writeValueAsString(value)) } get("CityTags") { ctx -> val value = db.soundDB.List .filter { it.Category == Category.City.name } .distinctBy { it.TAG } .sortedBy { it.TAG } .map { KeyValueMessage(it.TAG, it.Description) } ctx.result(objectmapper.writeValueAsString(value)) } post("Add") { try { val addvalue = objectmapper.readValue(it.body(), Soundbank::class.java) if (ValidString(addvalue.Description)) { if (ValidString(addvalue.TAG)) { if (ValidString(addvalue.Category)) { if (ValidString(addvalue.Language)) { if (ValidString(addvalue.Path)) { // check apakah TAG sudah ada untuk language dan category yang sama val exists = db.soundDB.List.any { sb -> sb.TAG == addvalue.TAG && sb.Language == addvalue.Language && sb.Category == addvalue.Category } if (!exists) { if (ValidFile(addvalue.Path)) { if (db.soundDB.Add(addvalue)) { db.soundDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to add soundbank to database"))) } else it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Invalid Path, file does not exist"))) } else it.status(400) .result(objectmapper.writeValueAsString(resultMessage("TAG=${addvalue.TAG} already exists for the same Language=${addvalue.Language} and Category=${addvalue.Category}"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Path"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Language"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Category"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid TAG"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Description"))) } catch (_: Exception) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid request body"))) } } delete("List") { // truncate soundbank table if (db.soundDB.Clear()) { db.soundDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate soundbank table"))) } } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.soundDB.DeleteByIndex(index.toInt())) { db.soundDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete soundbank with index $index"))) } } } patch("UpdateByIndex/{index}") { // update by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { // tidak ada path param index it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { val sb = db.soundDB.List.find { xx -> xx.index == index } if (sb == null) { // soundbank dengan index tersebut tidak ditemukan it.status(404).result(objectmapper.writeValueAsString(resultMessage("Soundbank with index $index not found"))) } else { // soundbank dengan index tersebut ditemukan, sekarang update val json: JsonNode = objectmapper.readTree(it.body()) if (json.isEmpty) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body"))) } else { val _description = json.get("Description").asText("") val _tag = json.get("TAG").asText("") val _category = json.get("Category").asText("") val _language = json.get("Language").asText("") val _path = json.get("Path").asText("") var changed = false if (ValidString(_description) && _description != sb.Description) { sb.Description = _description changed = true } if (ValidString(_tag) && _tag != sb.TAG) { sb.TAG = _tag changed = true } if (ValidString(_category) && _category != sb.Category) { if (Category.entries.any { cat -> cat.name == _category }) { sb.Category = _category changed = true } else { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Category"))) return@patch } } if (ValidString(_language) && _language != sb.Language) { sb.Language = _language changed = true } if (ValidString(_path) && _path != sb.Path) { if (ValidFile(_path)) { sb.Path = _path changed = true } else { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Path, file does not exist"))) return@patch } } if (changed) { if (db.soundDB.UpdateByIndex(index.toInt(), sb)) { db.soundDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to update soundbank with index $index"))) } else it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for soundbank with index $index"))) } } } } get("ExportXLSX") { val xlsxdata = db.soundDB.Export_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) } } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export soundbank to XLSX"))) } } post("ImportXLSX") { val uploaded = it.uploadedFile("file") if (uploaded == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded"))) return@post } try { val xlsx = XSSFWorkbook(uploaded.content()) if (db.soundDB.Import_XLSX(xlsx)) { db.soundDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import soundbank from XLSX"))) } } catch (e: Exception) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file"))) } } } path("MessageBank") { get("List") { // get messagebank list it.result(MariaDB.ArrayListtoString(db.messageDB.List)) } get("MessageIDs") { ctx -> val value = db.messageDB.List .distinctBy { it.ANN_ID } .sortedBy { it.ANN_ID } .map { KeyValueMessage(it.ANN_ID.toString(), it.Description) } ctx.result(objectmapper.writeValueAsString(value)) } post("Add") { val json: JsonNode = objectmapper.readTree(it.body()) val description = json.get("Description")?.asText("") ?: "" val language = json.get("Language")?.asText("") ?: "" val ann_id = json.get("ANN_ID")?.asInt()?.toUInt() ?: 0u val voice_type = json.get("Voice_Type")?.asText("") ?: "" val message_detail = json.get("Message_Detail")?.asText("") ?: "" val message_tags = json.get("Message_TAGS")?.asText("") ?: "" if (description.isNotEmpty()){ if (language.isNotEmpty() && Language.entries.any{ lang -> lang.name == language }){ if (ann_id>0u){ if (voice_type.isNotEmpty() && VoiceType.entries.any{ vt -> vt.name == voice_type }){ if (message_detail.isNotEmpty()){ if (message_tags.isNotEmpty()){ val mb = Messagebank(0u, description, language, ann_id, voice_type, message_detail, message_tags) if (db.messageDB.Add(mb)){ db.messageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to add messagebank to database"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Message_TAGS"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Message_Detail"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Voice_Type"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid ANN_ID"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Language"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Description"))) } delete("List") { // truncate messagebank table if (db.messageDB.Clear()) { db.messageDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate messagebank table"))) } } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.messageDB.DeleteByIndex(index.toInt())) { db.messageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("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(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { val mb = db.messageDB.List.find { xx -> xx.index == index } if (mb == null) { it.status(404).result(objectmapper.writeValueAsString(resultMessage("Messagebank with index $index not found"))) } else { val json: JsonNode = objectmapper.readTree(it.body()) if (json.isEmpty) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("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 } if (ValidString(_language) && _language != mb.Language) { 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(objectmapper.writeValueAsString(resultMessage("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.messageDB.UpdateByIndex(index.toInt(), mb)) { db.messageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to update messagebank with index $index"))) } else it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for messagebank with index $index"))) } } } } get("ExportXLSX") { val xlsxdata = db.messageDB.Export_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(objectmapper.writeValueAsString(resultMessage("Failed to export messagebank to XLSX"))) } } post("ImportXLSX") { val uploaded = it.uploadedFile("file") if (uploaded == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded"))) return@post } try { val xlsx = XSSFWorkbook(uploaded.content()) if (db.messageDB.Import_XLSX(xlsx)) { db.messageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import messagebank from XLSX"))) } } catch (e: Exception) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file"))) } } } path("LanguageLink") { get("List") { // get language link list it.result(MariaDB.ArrayListtoString(db.languageDB.List)) } post("Add"){ // Parse JSON from request body val json: JsonNode = objectmapper.readTree(it.body()) val tag = json.get("tag").asText("") val languages = json.get("language").asText("").split(";") println("Add Language Link, tag=$tag, languages=$languages") if (ValidString(tag)){ if (languages.all { xx -> Language.entries.any { yy -> yy.name.equals(xx,true)} }){ if (!db.languageDB.List.any { ll -> ll.TAG.equals(tag,true) }) { val newvalue = LanguageLink(0u, tag, languages.joinToString(";")) if (db.languageDB.Add(newvalue)){ db.languageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to add language link to database"))) println("Failed to add language link to database") } } else { it.status(400).result(objectmapper.writeValueAsString(resultMessage("TAG=$tag already exists"))) println("TAG=$tag already exists") } } else { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Contains unsupported language"))) println("Contains unsupported language") } } else { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid tag or language"))) println("Invalid tag") } } delete("List") { // truncate language link table if (db.languageDB.Clear()) { db.languageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate language link table"))) } } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.languageDB.DeleteByIndex(index.toInt())) { db.languageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("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(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { val ll = db.languageDB.List.find { xx -> xx.index == index } if (ll == null) { it.status(404).result(objectmapper.writeValueAsString(resultMessage("Language link with index $index not found"))) } else { val json: JsonNode = objectmapper.readTree(it.body()) if (json.isEmpty) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("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 } if (ValidString(_tag) && _tag != ll.TAG) { ll.TAG = _tag changed = true } if (changed) { if (db.languageDB.UpdateByIndex(index.toInt(), ll)) { db.languageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to update language link with index $index"))) } else it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for language link with index $index"))) } } } } get("ExportXLSX") { val xlsxdata = db.languageDB.Export_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(objectmapper.writeValueAsString(resultMessage("Failed to export language link to XLSX"))) } } post("ImportXLSX") { val uploaded = it.uploadedFile("file") if (uploaded == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded"))) return@post } try { val xlsx = XSSFWorkbook(uploaded.content()) if (db.languageDB.Import_XLSX(xlsx)) { db.languageDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import language link from XLSX"))) } } catch (e: Exception) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file"))) } } } path("ScheduleBank") { get("List") { // get timer list it.result(MariaDB.ArrayListtoString(db.scheduleDB.List)) } delete("List") { // truncate timer table if (db.scheduleDB.Clear()) { db.scheduleDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate schedulebank table"))) } } post("Add"){ // TODO add new schedule // recheck lagi tambahan steph val json: JsonNode = objectmapper.readTree(it.body()) val description = json.get("Description")?.asText("") ?: "" val day = json.get("Day")?.asText("") ?: "" val time = json.get("Time")?.asText("") ?: "" val soundpath = json.get("Soundpath")?.asText("") ?: "" val repeat = json.get("Repeat")?.asInt()?.toUByte() ?: 0u val enable = json.get("Enable")?.asBoolean() ?: false val broadcast_zones = json.get("BroadcastZones")?.asText("") ?: "" val language = json.get("Language")?.asText("") ?: "" if (ValidString(description)){ if (ValidString(day) && ValidScheduleDay(day)){ if (ValidString(time) && ValidScheduleTime(time)){ if (ValidString(soundpath) && ValidFile(soundpath)){ if (repeat in 0u..127u){ if (ValidString(broadcast_zones)){ val zones = broadcast_zones.split(";") if (zones.all { zz -> db.broadcastDB.List.any { xx -> xx.description.equals(zz,true) } }){ if (ValidString(language) && Language.entries.any{ lang -> lang.name == language }){ val newvalue = ScheduleBank( 0u, description, day, time, soundpath, repeat, enable, broadcast_zones, language ) if (db.scheduleDB.Add(newvalue)){ db.scheduleDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to add schedule to database"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Language"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Contains unsupported BroadcastZones"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid BroadcastZones"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Repeat, must be between 0-127"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Soundpath"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Time format, must be HH:mm"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Day format"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Description"))) } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.scheduleDB.DeleteByIndex(index.toInt())) { db.scheduleDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("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(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { val sb = db.scheduleDB.List.find { xx -> xx.index == index } if (sb == null) { it.status(404).result(objectmapper.writeValueAsString(resultMessage("Schedule with index $index not found"))) } else { val json: JsonNode = objectmapper.readTree(it.body()) if (json.isEmpty) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("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 } if (ValidString(_time) && _time != sb.Time) { if (ValidScheduleTime(_time)) { sb.Time = _time changed = true } else { it.status(400).result(objectmapper.writeValueAsString(resultMessage("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(objectmapper.writeValueAsString(resultMessage("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(objectmapper.writeValueAsString(resultMessage("Invalid Language"))) return@patch } } if (changed) { if (db.scheduleDB.UpdateByIndex(index.toInt(), sb)) { db.scheduleDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to update schedule with index $index"))) } else it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for schedule with index $index"))) } } } } get("ExportXLSX") { val xlsxdata = db.scheduleDB.Export_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(objectmapper.writeValueAsString(resultMessage("Failed to export schedulebank to XLSX"))) } } post("ImportXLSX") { val uploaded = it.uploadedFile("file") if (uploaded == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded"))) return@post } try { val xlsx = XSSFWorkbook(uploaded.content()) if (db.scheduleDB.Import_XLSX(xlsx)) { db.scheduleDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to import schedulebank from XLSX"))) } } catch (e: Exception) { it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file"))) } } } path("UserManagement") { get("List") { it.result(objectmapper.writeValueAsString(db.userDB.List)) } delete("List") { if (db.userDB.Clear()) { db.userDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to truncate user table"))) } } post("Add") { ctx -> val json: JsonNode = objectmapper.readTree(ctx.body()) val username = json.get("username").asText("") val password = json.get("password").asText("") val location = json.get("location").asText("") val airline_tags = json.get("airline_tags").asText("") val city_tags = json.get("city_tags").asText("") val messagebank_ann_id = json.get("messagebank_ann_id").asText("") val broadcastzones = json.get("broadcastzones").asText("") if (ValidStrings(listOf(username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones))) { if (!db.Username_exists(username)) { // check apakah ada airline tag yang tidak ada di soundbank val atags = airline_tags.split(";").map { it.trim() } .filter { it.isNotEmpty() }.distinct() val airlinetags = db.Get_AirlineCode_Tags() if (atags.all { tag -> airlinetags.any { it == tag } }) { // check apakah ada city tag yang tidak ada di soundbank val ctags = city_tags.split(";").map { it.trim() } .filter { it.isNotEmpty() }.distinct() val citytags = db.Get_City_Tags() if (ctags.all { tag -> citytags.any { it == tag } }) { val bzdesc = broadcastzones.split(";").map { it.trim() } .filter { it.isNotEmpty() }.distinct() val bzlist = db.Get_BroadcastZone_List() if (bzdesc.all { desc -> bzlist.any { it == desc } }) { val mbids = messagebank_ann_id.split(";") .map { it.trim() } .filter { it.isNotEmpty() }.distinct() .mapNotNull { it.toUIntOrNull() } val mbankids = db.Get_MessageID_List() if (mbids.all { id -> mbankids.any { it == id } }) { // semua valid, tambain ke database val newuser = UserDB( 0u, username, password, location, airline_tags, city_tags, messagebank_ann_id, broadcastzones ) if (db.userDB.Add(newuser)) { db.userDB.Resort() ctx.result(objectmapper.writeValueAsString(resultMessage("OK") )) } else ctx.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to add user to database"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Some ANN_ID not found in Messagebank") )) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Some broadcast zone tags not found in soundbank")) ) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Some city tags not found in soundbank"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Some airline tags not found in soundbank"))) } else ctx.status(400).result(objectmapper.writeValueAsString("Username already exists")) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Not all fields have value"))) } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.userDB.DeleteByIndex(index.toInt())) { db.userDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete user with index $index"))) } } patch("UpdateByIndex/{index}"){ ctx -> // update by index val index = ctx.pathParam("index").toUIntOrNull() if (index!=null){ val user = db.userDB.List.find { xx -> xx.index == index } if (user!=null){ val json : JsonNode = objectmapper.readTree(ctx.body()) if (!json.isEmpty){ val _username = json.get("username").asText("") val _password = json.get("password").asText("") val _location = json.get("location").asText("") val _airline_tags = json.get("airline_tags").asText("") val _city_tags = json.get("city_tags").asText("") val _messagebank_ann_id = json.get("messagebank_ann_id").asText("") val _broadcastzones = json.get("broadcastzones").asText("") if (ValidStrings(listOf(_username, _password, _location, _airline_tags, _city_tags, _messagebank_ann_id, _broadcastzones))) { val _otherusername = db.userDB.List.find { xx -> xx.username.equals(_username, true) && xx.index != index } if (_otherusername == null) { // belum ada user lain yang pakai username ini val atags = _airline_tags.split(";").map { it.trim() }.filter { it.isNotEmpty() }.distinct() val ctags = _city_tags.split(";").map { it.trim() }.filter { it.isNotEmpty() }.distinct() val msgids = _messagebank_ann_id.split(";").map { it.trim() }.filter { it.isNotEmpty() }.distinct().mapNotNull { it.toUIntOrNull() } val bzdesc = _broadcastzones.split(";").map { it.trim() }.filter { it.isNotEmpty() }.distinct() val airline_tags = db.Get_AirlineCode_Tags() val city_tags = db.Get_City_Tags() val msgbankids = db.Get_MessageID_List() val bzlist = db.Get_BroadcastZone_List() if (atags.all { tag -> airline_tags.any { it == tag } }) { if (ctags.all { tag -> city_tags.any { it == tag } }) { if (msgids.all { tag -> msgbankids.any { it == tag } }) { if (bzdesc.all { tag -> bzlist.any { it == tag } }) { val editeduser = UserDB(index, _username, _password, _location, _airline_tags, _city_tags, _messagebank_ann_id, _broadcastzones) if (!user.isEqual(editeduser)){ if (db.userDB.UpdateByIndex(index.toInt(), editeduser)){ db.userDB.Resort() ctx.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else ctx.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to update user with index $index"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for user with index $index"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Some broadcast zone is not found in Broadcast Zone list"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Some ANN_ID not found in Messagebank"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Some city tags not found in soundbank"))) } else ctx.status(400).result(objectmapper.writeValueAsString("Some airline tags not found in soundbank")) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Username already exists for another user"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Not all fiels have value"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("User with index $index not found"))) } else ctx.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } get("ExportXLSX") { val xlsxdata = db.userDB.Export_XLSX() if (xlsxdata != null) { it.header( "Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) it.header("Content-Disposition", "attachment; filename=\"userdb.xlsx\"") it.outputStream().use { out -> xlsxdata.write(out) } } else { it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to export user table to XLSX"))) } } post("ImportXLSX") { val uploaded = it.uploadedFile("file") if (uploaded == null) { it.status(400) .result(objectmapper.writeValueAsString(resultMessage("No file uploaded"))) return@post } try { val xlsx = XSSFWorkbook(uploaded.content()) if (db.userDB.Import_XLSX(xlsx)) { db.userDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to import user table from XLSX"))) } } catch (e: Exception) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file"))) } } //TODO kirim list message dan broadcast zones untuk ADD/Edit schedule get("GetMessageAndBroadcastZones") { val result = object { //TODO filter message without input variable val messages = db.messageDB.List val broadcastzones = db.broadcastDB.List } it.result(objectmapper.writeValueAsString(result)) } } path("Log") { get("List") { get1 -> val logdate = get1.queryParam("date") ?: "" val logfilter = get1.queryParam("filter") ?: "" if (ValiDateForLogHtml(logdate)) { if (ValidString(logfilter)) { // ada log filter db.GetLogForHtml(logdate, logfilter) { get1.result(MariaDB.ArrayListtoString(it)) } } else { db.GetLogForHtml(logdate) { get1.result(MariaDB.ArrayListtoString(it)) } } } else { println("Invalid logdate=$logdate") get1.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid logdate"))) } } get("ExportXLSX") { get1 -> val logdate = get1.queryParam("date") ?: "" val logfilter = get1.queryParam("filter") ?: "" println("Export log to XLSX, date=$logdate, filter=$logfilter") if (ValiDateForLogHtml(logdate)) { val xlsxdata = if (ValidString(logfilter)) { db.Export_Log_XLSX(logdate.replace('-','/'), logfilter) } else { db.Export_Log_XLSX(logdate.replace('-','/'), "") } if (xlsxdata != null) { get1.header( "Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) get1.header("Content-Disposition", "attachment; filename=\"log_$logdate.xlsx\"") get1.outputStream().use { out -> xlsxdata.write(out) } } else { get1.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export log to XLSX"))) } } else get1.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid logdate"))) } } path("BroadcastZones"){ get("List") { it.result(MariaDB.ArrayListtoString(db.broadcastDB.List)) } get("BroadcastZoneDescriptions") { ctx -> val value = db.broadcastDB.List .distinctBy { it.description } .map { it.description } ctx.result(objectmapper.writeValueAsString(value)) } delete("List") { // truncate broadcast zones table if (db.broadcastDB.Clear()) { db.broadcastDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate broadcast zones table"))) } } post("Add") { val json : JsonNode = objectmapper.readTree(it.body()) val _description = json.get("description").asText("") val _soundchannel = json.get("SoundChannel").asText("") val _box = json.get("Box").asText("") val _relay = json.get("Relay").asText("") if (ValidString(_description)){ if (ValidString(_soundchannel)){ if (ValidString(_box)){ if (ValidString(_relay)){ val newbp = BroadcastZones(0u,_description,_soundchannel,_box,_relay) if (db.broadcastDB.Add(newbp)){ db.broadcastDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to add broadcast zone to database"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Relay"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Box"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid SoundChannel"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid description"))) } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.broadcastDB.DeleteByIndex(index.toInt())) { db.broadcastDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete broadcast zone with index $index"))) } } } patch("UpdateByIndex/{index}") { // update by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { val bz = db.broadcastDB.List.find { xx -> xx.index == index } if (bz == null) { it.status(404).result(objectmapper.writeValueAsString(resultMessage("Broadcast zone with index $index not found"))) } else { val json: JsonNode = objectmapper.readTree(it.body()) if (json.isEmpty) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body"))) } else { val _description = json.get("description").asText("") val _soundchannel = json.get("SoundChannel").asText("") val _box = json.get("Box").asText("") val _relay = json.get("Relay").asText("") var changed = false if (ValidString(_description) && _description != bz.description) { bz.description = _description changed = true } if (ValidString(_soundchannel) && _soundchannel != bz.SoundChannel) { bz.SoundChannel = _soundchannel changed = true } if (ValidString(_box) && _box != bz.id) { bz.id = _box changed = true } if (ValidString(_relay) && _relay != bz.bp) { bz.bp = _relay changed = true } if (changed) { if (db.broadcastDB.UpdateByIndex(index.toInt(), bz)) { db.broadcastDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to update broadcast zone with index $index"))) } else it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for broadcast zone with index $index"))) } } } } get("ExportXLSX") { val xlsxdata = db.broadcastDB.Export_XLSX() if (xlsxdata != null) { it.header( "Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) it.header("Content-Disposition", "attachment; filename=\"broadcastzones.xlsx\"") it.outputStream().use { out -> xlsxdata.write(out) } } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export broadcast zones to XLSX"))) } } post("ImportXLSX") { val uploaded = it.uploadedFile("file") if (uploaded == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded"))) return@post } try { val xlsx = XSSFWorkbook(uploaded.content()) if (db.broadcastDB.Import_XLSX(xlsx)) { db.broadcastDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import broadcast zones from XLSX"))) } } catch (e: Exception) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file"))) } } } path("SoundChannel"){ get("List"){ it.result(MariaDB.ArrayListtoString(db.soundchannelDB.List)) } get("SoundChannelDescriptions") { it.result(objectmapper.writeValueAsString(db.Get_SoundChannel_List())) } delete("List") { // truncate sound channel table if (db.soundchannelDB.Clear()) { db.soundchannelDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate sound channel table"))) } } patch("UpdateByIndex/{index}"){ val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { val sc = db.soundchannelDB.List.find { xx -> xx.index == index } if (sc == null) { println("Sound channel with index $index not found") it.status(404).result(objectmapper.writeValueAsString(resultMessage("Sound channel with index $index not found"))) } else { val json: JsonNode = objectmapper.readTree(it.body()) println("Received JSON: $json") if (json.isEmpty) { println("UpdateByIndex with index=$index has empty body") it.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body"))) } else { val _channel = json.get("description").asText("") val _ip = json.get("ip").asText("") println("Update sound channel with index $index, channel=$_channel, ip=$_ip") if (ValidString(_channel)){ if (ValidIPV4(_ip)){ if (_channel.equals(sc.channel) && _ip.equals(sc.ip)) { println("Nothing has changed for sound channel with index $index") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for sound channel with index $index"))) return@patch } else { // cek apakah ada soundchannel lain yang pakai ip dan channel yang sama val othersc = db.soundchannelDB.List.filter { sc -> sc.ip == _ip }.filter { sc -> sc.index != index } if (othersc.isNotEmpty()){ it.status(400).result(objectmapper.writeValueAsString(resultMessage("This IP address is already used by another sound channel"))) } else { // ada sesuatu yang ganti val newsc = SoundChannel(0u, _channel, _ip) if (db.soundchannelDB.UpdateByIndex(index.toInt(), newsc)) { println("Updated sound channel with index $index") db.soundchannelDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { println("Failed to update sound channel with index $index") it.status(500) .result(objectmapper.writeValueAsString(resultMessage("Failed to update sound channel with index $index"))) } } } } else { println("Invalid IP address") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid IP address"))) } } else { println("Invalid channel") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid channel"))) } } } } } get("ExportXLSX"){ val xlsxdata = db.soundchannelDB.Export_XLSX() if (xlsxdata != null) { it.header( "Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) it.header("Content-Disposition", "attachment; filename=\"soundchannel.xlsx\"") it.outputStream().use { out -> xlsxdata.write(out) } } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export sound channel to XLSX"))) } } post("ImportXLSX"){ val uploaded = it.uploadedFile("file") if (uploaded == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded"))) return@post } try { val xlsx = XSSFWorkbook(uploaded.content()) if (db.soundchannelDB.Import_XLSX(xlsx)) { db.soundchannelDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import sound channel from XLSX"))) } } catch (e: Exception) { it.status(400) .result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file"))) } } } // Steph : coba tambah untuk QueuePaging Table. Belum ada di JS file(?) path("QueuePaging"){ get("List"){ it.result(MariaDB.ArrayListtoString(db.queuepagingDB.List)) } delete("List"){ // truncate queue paging table if (db.queuepagingDB.Clear()) { db.queuepagingDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate queue paging table"))) } } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.queuepagingDB.DeleteByIndex(index.toInt())) { db.queuepagingDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete queue paging with index $index"))) } } } } // Steph : coba tambah untuk QueueTable Table. Belum ada di JS file(?) path("QueueTable"){ get("List"){ it.result(MariaDB.ArrayListtoString(db.queuetableDB.List)) } delete("List"){ // truncate queue table if (db.queuetableDB.Clear()) { db.queuetableDB.Get() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate queue sound table"))) } } delete("DeleteByIndex/{index}") { // delete by index val index = it.pathParam("index").toUIntOrNull() if (index == null) { it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index"))) } else { if (db.queuetableDB.DeleteByIndex(index.toInt())) { db.queuetableDB.Resort() it.result(objectmapper.writeValueAsString(resultMessage("OK"))) } else { it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete queue sound with index $index"))) } } } } } } }.start(listenPort) } fun CheckUsers(ctx: Context) { val user = ctx.sessionAttribute("user") if (user == null) { ctx.redirect("login.html") } val foundUser = userlist.find { it.first == user } if (foundUser == null) { ctx.redirect("login.html") } } fun Stop() { app?.stop() } }