From ea1defa78e92fd22a4d9f9f2de59559746eeb919 Mon Sep 17 00:00:00 2001 From: rdkartono Date: Tue, 2 Sep 2025 12:34:15 +0700 Subject: [PATCH] commit 02/09/2025 --- src/Main.kt | 33 +++++++--- src/codes/Somecodes.kt | 51 +++++++++++++++- src/database/Log.kt | 19 +----- src/database/MariaDB.kt | 36 +++++++---- src/web/WebApp.kt | 130 +++++++++++++++++++++++++++++++++++++--- 5 files changed, 224 insertions(+), 45 deletions(-) diff --git a/src/Main.kt b/src/Main.kt index ef14507..856a9f3 100644 --- a/src/Main.kt +++ b/src/Main.kt @@ -13,9 +13,9 @@ import web.WebApp fun main() { - if (Platform.isWindows()){ + if (Platform.isWindows()) { // supaya OSHI bisa mendapatkan CPU usage di Windows seperti di Task Manager - GlobalConfig.set(GlobalConfig.OSHI_OS_WINDOWS_CPU_UTILITY,true) + GlobalConfig.set(GlobalConfig.OSHI_OS_WINDOWS_CPU_UTILITY, true) } Logger.info("Application started" as Any) val audioPlayer = AudioPlayer(44100) // 44100 Hz sampling rate @@ -23,7 +23,7 @@ fun main() { val content = ContentCache() val db = MariaDB() CoroutineScope(Dispatchers.Default).launch { - while (isActive){ + while (isActive) { delay(1000) val broadcastzones = db.GetBroadcastZones() // baca dulu queue paging, prioritas 1 @@ -32,14 +32,17 @@ fun main() { if (it.BroadcastZones.isNotBlank()) { val zz = it.BroadcastZones.split(";") // cek apakah semua target broadcast zone dari queue paging ada di dalam database broadcast zones - if (zz.all { z -> broadcastzones.any { bz -> bz.equals(z) } }){ + if (zz.all { z -> broadcastzones.any { bz -> bz.equals(z) } }) { // semua target broadcast zone valid, sekarang cek apakah semua target broadcast zone idle } else { // ada broadcast zone yang tidak valid, delete from queue paging db.Delete_Queue_Paging_by_index(it.index) //TODO check log message yang benar - db.Add_Log("AAS", "Cancelled paging message with index ${it.index} due to invalid broadcast zone") + db.Add_Log( + "AAS", + "Cancelled paging message with index ${it.index} due to invalid broadcast zone" + ) } } else { // invalid broadcast zone, delete from queue paging @@ -51,16 +54,32 @@ fun main() { // baca kemudian queue table, prioritas 2 db.Read_Queue_Table().forEach { if (it.BroadcastZones.isNotBlank()) { + val zz = it.BroadcastZones.split(";") + // cek apakah semua target broadcast zone dari queue table ada di dalam database broadcast zones + if (zz.all { z -> broadcastzones.any { bz -> bz.equals(z) } }) { + // semua target broadcast zone valid, sekarang cek apakah semua target broadcast zone idle + } else { + // ada broadcast zone yang tidak valid, delete from queue table + db.Delete_Queue_Table_by_index(it.index) + //TODO check log message yang benar + db.Add_Log( + "AAS", + "Cancelled table message with index ${it.index} due to invalid broadcast zone" + ) + } } else { // invalid broadcast zone, delete from queue table db.Delete_Queue_Table_by_index(it.index) + // TODO check log message yang benar + db.Add_Log("AAS", "Cancelled table message with index ${it.index} due to empty broadcast zone") } } } } - val web = WebApp(3030, + val web = WebApp( + 3030, listOf( Pair("admin", "password"), Pair("user", "password") @@ -69,6 +88,4 @@ fun main() { web.Start() - - } diff --git a/src/codes/Somecodes.kt b/src/codes/Somecodes.kt index b55e81d..6701d05 100644 --- a/src/codes/Somecodes.kt +++ b/src/codes/Somecodes.kt @@ -21,7 +21,8 @@ class Somecodes { val processor: CentralProcessor = si.hardware.processor val memory : GlobalMemory = si.hardware.memory val datetimeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss") - + val dateformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy") + val timeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss") const val KB_threshold = 1024.0 const val MB_threshold = KB_threshold * 1024.0 const val GB_threshold = MB_threshold * 1024.0 @@ -67,6 +68,10 @@ class Somecodes { } } + /** + * Get CPU usage using OSHI library. + * @param cb A callback function that receives the CPU usage as a string. + */ fun getCPUUsage(cb : Consumer){ CoroutineScope(Dispatchers.Default).launch { val prev = processor.systemCpuLoadTicks @@ -106,16 +111,60 @@ class Somecodes { , (usedMemory.toDouble() / totalMemory * 100)) } + /** + * Check if a value is a valid non-blank string. + * @param value The value to check. + * @return True if the value is a non-blank string, false otherwise. + */ fun ValidString(value: Any) : Boolean { return value is String && value.isNotBlank() } + /** + * Check if a string is a valid file path and the file exists. + * @param value The string to check. + * @return True if the string is a valid file path, false otherwise. + */ fun ValidFile(value : String) : Boolean { if (value.isNotBlank()){ return Files.exists(Path.of(value)) } return false } + + /** + * Check if a string is a valid date in the format "dd/MM/yyyy". + * @param value The string to check. + * @return True if the string is a valid date, false otherwise. + */ + fun ValidDate(value: String): Boolean{ + return try{ + if (ValidString(value)){ + dateformat1.parse(value) + true + } else throw Exception() + + } catch (_: Exception){ + false + } + } + + /** + * Check if a string is a valid time in the format "hh:mm:ss". + * @param value The string to check. + * @return True if the string is a valid time, false otherwise. + */ + fun ValidTime(value: String): Boolean{ + return try{ + if (ValidString(value)){ + timeformat1.parse(value) + true + } else throw Exception() + + } catch (_: Exception){ + false + } + } } diff --git a/src/database/Log.kt b/src/database/Log.kt index 8af4193..6401407 100644 --- a/src/database/Log.kt +++ b/src/database/Log.kt @@ -1,25 +1,10 @@ package database +@Suppress("unused") data class Log( val index: ULong, val datenya: String, val timenya: String, val machine: String, val description : String -) { - @Suppress("unused") - companion object { - - fun ValidDate(date: String): Boolean { - // Simple date validation (DD/MM/YYYY) - val regex = Regex("""^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/\d{4}$""") - return regex.matches(date) - } - - fun validTime(time: String): Boolean { - // Simple time validation (HH:MM:SS) - val regex = Regex("""^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$""") - return regex.matches(time) - } - } -} +) diff --git a/src/database/MariaDB.kt b/src/database/MariaDB.kt index a3b4a64..83d25e2 100644 --- a/src/database/MariaDB.kt +++ b/src/database/MariaDB.kt @@ -217,7 +217,7 @@ class MariaDB ( /** * Reloads the ScheduleBank list from the database. */ - private fun Reload_Schedulebank() { + fun Reload_Schedulebank() { SchedulebankList.clear() try { val statement = connection?.createStatement() @@ -266,22 +266,24 @@ class MariaDB ( /** * Clears all entries from the schedulebank table in the database and the local list. */ - fun Clear_Schedulebank() { + fun Clear_Schedulebank() : Boolean { try { val statement = connection?.createStatement() // use TRUNCATE to reset auto increment index statement?.executeUpdate("TRUNCATE TABLE schedulebank") Logger.info("Schedulebank table cleared" as Any) SchedulebankList.clear() + return true } catch (e : Exception) { Logger.error("Error clearing schedulebank table: ${e.message}" as Any) } + return false } /** * Reloads the language link list from the database. */ - private fun Reload_LanguageLink() { + fun Reload_LanguageLink() { LanguageLinkList.clear() try { val statement = connection?.createStatement() @@ -324,22 +326,24 @@ class MariaDB ( /** * Clears all entries from the language link table in the database and the local list. */ - fun Clear_LanguageLink() { + fun Clear_LanguageLink() : Boolean { try { val statement = connection?.createStatement() // use TRUNCATE to reset auto increment index statement?.executeUpdate("TRUNCATE TABLE languagelink") Logger.info("LanguageLink table cleared" as Any) LanguageLinkList.clear() + return true } catch (e : Exception) { Logger.error("Error clearing LanguageLink table: ${e.message}" as Any) } + return false } /** * Reloads the soundbank list from the database. */ - private fun Reload_Soundbank() { + fun Reload_Soundbank() { SoundbankList.clear() try { @@ -387,22 +391,24 @@ class MariaDB ( /** * Clears all entries from the soundbank table in the database and the local list. */ - fun Clear_Soundbank() { + fun Clear_Soundbank() : Boolean{ try { val statement = connection?.createStatement() // use TRUNCATE to reset auto increment index statement?.executeUpdate("TRUNCATE TABLE soundbank") Logger.info("Soundbank table cleared" as Any) SoundbankList.clear() + return true } catch (e : Exception) { Logger.error("Error clearing soundbank table: ${e.message}" as Any) } + return false } /** * Reloads the messagebank list from the database. */ - private fun Reload_Messagebank() { + fun Reload_Messagebank() { MessagebankList.clear() try { val statement = connection?.createStatement() @@ -450,16 +456,18 @@ class MariaDB ( /** * Clears all entries from the messagebank table in the database and the local list. */ - fun Clear_Messagebank() { + fun Clear_Messagebank() : Boolean{ try { val statement = connection?.createStatement() // use TRUNCATE to reset auto increment index statement?.executeUpdate("TRUNCATE TABLE messagebank") Logger.info("Messagebank table cleared" as Any) MessagebankList.clear() + return true } catch (e : Exception) { Logger.error("Error clearing messagebank table: ${e.message}" as Any) } + return false } /** @@ -516,15 +524,17 @@ class MariaDB ( /** * Clears all entries from the queue_table in the database. */ - fun Clear_Queue_Table() { + fun Clear_Queue_Table() : Boolean { try { val statement = connection?.createStatement() // use TRUNCATE to reset auto increment index statement?.executeUpdate("TRUNCATE TABLE queue_table") Logger.info("Queue table cleared" as Any) + return true } catch (e : Exception) { Logger.error("Error clearing queue table: ${e.message}" as Any) } + return false } /** @@ -578,15 +588,17 @@ class MariaDB ( /** * Clears all entries from the queue_paging in the database. */ - fun Clear_Queue_Paging(){ + fun Clear_Queue_Paging() : Boolean{ try { val statement = connection?.createStatement() // use TRUNCATE to reset auto increment index statement?.executeUpdate("TRUNCATE TABLE queue_paging") Logger.info("Queue paging table cleared" as Any) + return true } catch (e : Exception) { Logger.error("Error clearing queue paging table: ${e.message}" as Any) } + return false } /** @@ -639,15 +651,17 @@ class MariaDB ( /** * Clears all entries from the broadcast_zones in the database. */ - fun Clear_BroadcastZones() { + fun Clear_BroadcastZones() : Boolean { try { val statement = connection?.createStatement() // use TRUNCATE to reset auto increment index statement?.executeUpdate("TRUNCATE TABLE broadcast_zones") Logger.info("Broadcast zones table cleared" as Any) + return true } catch (e : Exception) { Logger.error("Error clearing broadcast zones table: ${e.message}" as Any) } + return false } } \ No newline at end of file diff --git a/src/web/WebApp.kt b/src/web/WebApp.kt index 9d8491a..7e0704d 100644 --- a/src/web/WebApp.kt +++ b/src/web/WebApp.kt @@ -1,10 +1,13 @@ package web import codes.Somecodes +import codes.Somecodes.Companion.ValidDate +import codes.Somecodes.Companion.ValidString import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import database.MariaDB 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.path import io.javalin.apibuilder.ApiBuilder.post @@ -111,12 +114,7 @@ class WebApp(val listenPort: Int, val userlist: List>, val println("getTimerList command received") SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.SchedulebankList)) } - "getLog" ->{ - println("getLog command received") - } - "getSetting" ->{ - println("getSetting command received") - } + else -> { SendReply(wsMessageContext, cmd.command, "Unknown command") } @@ -135,19 +133,111 @@ class WebApp(val listenPort: Int, val userlist: List>, val } path("soundbank.html") { before {CheckUsers(it)} + get("List"){ + // get soundbank list + it.result(MariaDB.ArrayListtoString(db.SoundbankList)) + } + delete("List"){ + // truncate soundbank table + if (db.Clear_Soundbank()){ + it.result("OK") + } else { + it.status(500).result("Failed to truncate soundbank table") + } + } + delete("DeleteByIndex/{index}"){ + // delete by index + val index = it.pathParam("index").toUIntOrNull() + if (index == null){ + it.status(400).result("Invalid index") + } else{ + if (db.Delete_Soundbank_by_index(index)){ + it.result("OK") + } else { + it.status(500).result("Failed to delete soundbank with index $index") + } + } + + } + } path("messagebank.html") { before { CheckUsers(it) } - + get("List"){ + // get messagebank list + it.result(MariaDB.ArrayListtoString(db.MessagebankList)) + } + delete("List"){ + // truncate messagebank table + if (db.Clear_Messagebank()){ + it.result("OK") + } else { + it.status(500).result("Failed to truncate messagebank table") + } + } + delete("DeleteByIndex/{index}"){ + // delete by index + val index = it.pathParam("index").toUIntOrNull() + if (index == null){ + it.status(400).result("Invalid index") + } else{ + if (db.Delete_Messagebank_by_index(index)){ + it.result("OK") + } else { + it.status(500).result("Failed to delete messagebank with index $index") + } + } + } } path("language.html") { before { CheckUsers(it) } + get("List"){ + // get language link list + it.result(MariaDB.ArrayListtoString(db.LanguageLinkList)) + } + delete("List"){ + // truncate language link table + if (db.Clear_LanguageLink()){ + it.result("OK") + } else { + it.status(500).result("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("Invalid index") + } else{ + if (db.Delete_LanguageLink_by_index(index)){ + it.result("OK") + } else { + it.status(500).result("Failed to delete language link with index $index") + } + } + } } path("log.html") { before { CheckUsers(it) } + get("List//"){ get1 -> + val logdate = get1.pathParam("logdate") + val logfilter = get1.pathParam("logfilter") + if (ValidDate(logdate)){ + if (ValidString(logfilter)){ + // ada log filter + db.GetLog(logdate, logfilter){ + get1.result(MariaDB.ArrayListtoString(it)) + } + } else { + db.GetLog(logdate){ + get1.result(MariaDB.ArrayListtoString(it)) + } + } + } else get1.status(400).result("Invalid logdate") + } } path("setting.html") { @@ -156,7 +246,31 @@ class WebApp(val listenPort: Int, val userlist: List>, val } path("timer.html") { before { CheckUsers(it) } - + get("List"){ + // get timer list + it.result(MariaDB.ArrayListtoString(db.SchedulebankList)) + } + delete("List"){ + // truncate timer table + if (db.Clear_Schedulebank()){ + it.result("OK") + } else { + it.status(500).result("Failed to truncate schedulebank table") + } + } + delete("DeleteByIndex/{index}"){ + // delete by index + val index = it.pathParam("index").toUIntOrNull() + if (index == null){ + it.status(400).result("Invalid index") + } else{ + if (db.Delete_Schedulebank_by_index(index)){ + it.result("OK") + } else { + it.status(500).result("Failed to delete schedule with index $index") + } + } + } } } }.start(listenPort)