1446 lines
94 KiB
Kotlin
1446 lines
94 KiB
Kotlin
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<Pair<String, String>>) {
|
|
|
|
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<String?>("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()
|
|
|
|
}
|
|
} |