commit 27/10/2025

This commit is contained in:
2025-10-27 16:02:57 +07:00
parent 2986433706
commit 0ef35b2b0c
26 changed files with 1106 additions and 433 deletions

View File

@@ -33,13 +33,10 @@ lateinit var audioPlayer: AudioPlayer
val StreamerOutputs: MutableMap<String, BarixConnection> = HashMap()
lateinit var udpreceiver: UDPReceiver
lateinit var tcpreceiver: TCPReceiver
const val version = "0.0.11 (24/10/2025)"
const val version = "0.0.12 (27/10/2025)"
// AAS 64 channels
const val max_channel = 64
// dipakai untuk pilih voice type, bisa diganti via web nanti
var selected_voice = VoiceType.VOICE_1.name
// dipakai untuk ambil messagebank berdasarkan id
val urutan_bahasa = listOf(
Language.INDONESIA.name,
@@ -168,8 +165,6 @@ fun main() {
Logger.error { "Failed to start TCP Receiver on port 5002" }
}
val androidserver = TCP_Android_Command_Server()
androidserver.StartTcpServer(5003){
Logger.info { it }

View File

@@ -16,6 +16,7 @@ import codes.configKeys
import content.Category
import content.Language
import content.ScheduleDay
import content.VoiceType
import database.BroadcastZones
import database.Messagebank
import database.QueueTable
@@ -137,8 +138,11 @@ class MainExtension01 {
*/
fun Get_MessageBank_by_id(id: Int, languages: List<String> = urutan_bahasa): ArrayList<Messagebank> {
val mb_list = ArrayList<Messagebank>()
var selected_voice = config.Get(configKeys.DEFAULT_VOICE_TYPE.key)
if (selected_voice.isEmpty()) selected_voice = VoiceType.VOICE_1.name
languages.forEach { lang ->
db.messageDB.List.find { mb -> mb.ANN_ID == id.toUInt() && mb.Language.equals(lang, true) && mb.Voice_Type.equals(selected_voice, true) }
db.messageDB.List
.find { mb -> mb.ANN_ID == id.toUInt() && mb.Language.equals(lang, true) && mb.Voice_Type.equals(selected_voice, true) }
?.let {
mb_list.add(it)
}
@@ -656,8 +660,6 @@ class MainExtension01 {
contentCache.addAudioFile(filenya, afi)
}
}
}
val targetfile = SoundbankResult_directory.resolve(
Make_WAV_FileName(
@@ -752,7 +754,7 @@ class MainExtension01 {
val zz = qa.BroadcastZones.split(";")
if (AllBroadcastZonesValid(zz)){
val ips = BroadcastZones_to_SoundChannel_IP(zz)
val ann_id = Get_ANN_ID(qa.Message)
val ann_id = Get_ANN_ID(qa.SB_TAGS)
if (ann_id>0){
if (AllStreamerOutputIdle(ips)){
val mblist = Get_MessageBank_by_id(ann_id, qa.Language.split(";"))

View File

@@ -118,15 +118,15 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
udp.send(DatagramPacket(chunk, chunk.size, inet))
delay(2)
} catch (e: Exception) {
cbFail.accept("SendData to $ipaddress:$port failed, message: ${e.message}")
cbFail.accept("SendData to $ipaddress failed, message: ${e.message}")
return@launch
}
}
cbOK.accept("SendData to $channel ($ipaddress:$port) succeeded, ${data.size} bytes sent")
cbOK.accept("SendData to $channel ($ipaddress) succeeded, ${data.size} bytes sent")
}
}
} else cbFail.accept("SendData to $ipaddress:$port failed, data is empty")
} else cbFail.accept("SendData to $ipaddress failed, data is empty")
}

View File

@@ -1,6 +1,5 @@
package codes
import codes.Somecodes.Companion.Soundbank_directory
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import content.Category
@@ -23,6 +22,7 @@ import java.nio.file.Files
import java.nio.file.Path
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.function.BiConsumer
import java.util.function.Consumer
import kotlin.io.path.name
@@ -77,6 +77,110 @@ class Somecodes {
)
}
/**
* Delete old PagingResult files older than specified days.
* If PagingResult directory does not exist, callback with -1,-1.
* @param daysOlder Number of days to determine old files, default to 7 days.
* @param cb Callback function of Success count and Failed count.
*/
fun Delete_Old_PagingResult_Files(daysOlder: Int, cb: BiConsumer<Int, Int>){
var deleted = 0
var failed = 0
if (Files.isDirectory(PagingResult_directory)){
val cutoffTime = System.currentTimeMillis() - daysOlder.toLong() * 24 * 60 * 60 * 1000
Files.list(PagingResult_directory).forEach {
try{
val fileTime = Files.getLastModifiedTime(it).toMillis()
if (fileTime < cutoffTime){
Files.delete(it)
Logger.info{ "Deleted old PagingResult file ${it.toAbsolutePath()}" }
deleted++
}
} catch (e: Exception){
Logger.error { "Failed to delete file ${it.toAbsolutePath()}: ${e.message}" }
failed++
}
}
cb.accept(deleted, failed)
} else cb.accept(-1,-1)
}
/**
* Clear all files in PagingResult directory.
* If PagingResult directory does not exist, callback with -1,-1.
* @param cb Callback function of Success count and Failed count.
*/
fun Clear_PagingResult_Directory(cb : BiConsumer<Int, Int>){
var deleted = 0
var failed = 0
if (Files.isDirectory(PagingResult_directory)){
Files.list(PagingResult_directory).forEach {
try{
Files.delete(it)
Logger.info{ "Deleted file ${it.toAbsolutePath()}" }
deleted++
} catch (e: Exception){
Logger.error { "Failed to delete file ${it.toAbsolutePath()}: ${e.message}" }
failed++
}
}
cb.accept(deleted, failed)
} else cb.accept(-1,-1)
}
/**
* Clear all files in SoundbankResult directory.
* If SoundbankResult directory does not exist, callback with -1,-1.
* @param cb Callback function of Success count and Failed count.
*/
fun Clear_SoundbankResult_Directory(cb : BiConsumer<Int, Int>){
var deleted = 0
var failed = 0
if (Files.isDirectory(SoundbankResult_directory)){
Files.list(SoundbankResult_directory).forEach {
try{
Files.delete(it)
Logger.info{ "Deleted file ${it.toAbsolutePath()}" }
deleted++
} catch (e: Exception){
Logger.error { "Failed to delete file ${it.toAbsolutePath()}: ${e.message}" }
failed++
}
}
cb.accept(deleted, failed)
} else cb.accept(-1,-1)
}
/**
* Delete old SoundbankResult files older than specified days.
* If SoundbankResult directory does not exist, callback with -1,-1.
* @param daysOlder Number of days to determine old files, default to 7 days.
* @param cb Callback function of Success count and Failed count.
*/
fun Delete_Old_SoundbankResult_Files(daysOlder: Int=7, cb: BiConsumer<Int, Int>){
var deleted = 0
var failed = 0
if (Files.isDirectory(SoundbankResult_directory)){
val cutoffTime = System.currentTimeMillis() - daysOlder.toLong() * 24 * 60 * 60 * 1000
Files.list(SoundbankResult_directory).forEach {
try{
val fileTime = Files.getLastModifiedTime(it).toMillis()
if (fileTime < cutoffTime){
Files.delete(it)
Logger.info{ "Deleted old SoundbankResult file ${it.toAbsolutePath()}" }
deleted++
}
} catch (e: Exception){
Logger.error { "Failed to delete file ${it.toAbsolutePath()}: ${e.message}" }
failed++
}
}
cb.accept(deleted, failed)
} else cb.accept(-1,-1)
}
fun ExtractFilesFromClassPath(resourcePath: String, outputDir: Path) {
try {
val resource = Somecodes::class.java.getResource(resourcePath)
@@ -357,11 +461,26 @@ class Somecodes {
*/
fun ValidFile(value : String) : Boolean {
if (value.isNotBlank()){
return Files.exists(Path.of(value))
return ValidFile(Path.of(value))
}
return false
}
fun ValidFile(value : Path) : Boolean {
return Files.exists(value) && Files.isRegularFile(value)
}
fun ValidDirectory(value : String) : Boolean {
if (value.isNotBlank()){
return ValidDirectory(Path.of(value))
}
return false
}
fun ValidDirectory(value : Path) : Boolean {
return Files.exists(value) && Files.isDirectory(value)
}
/**
* Check if a string is a valid date in the format "dd/MM/yyyy".
* @param value The string to check.

View File

@@ -1,5 +1,6 @@
package codes
import content.VoiceType
import org.tinylog.Logger
import java.nio.file.Files
import java.nio.file.Paths
@@ -66,6 +67,7 @@ class configFile {
config[configKeys.WEBAPP_VIEWER_USERNAME.key] = "viewer"
config[configKeys.WEBAPP_VIEWER_PASSWORD.key] = "password"
config[configKeys.WEBAPP_PORT.key] = "3030"
config[configKeys.DEFAULT_VOICE_TYPE.key] = VoiceType.VOICE_1.name
Save()
}
}

View File

@@ -11,6 +11,7 @@ enum class configKeys(val key: String) {
REMARK_GBD("remark.GBD"),
REMARK_GFC("remark.GFC"),
REMARK_FLD("remark.FLD"),
DEFAULT_VOICE_TYPE("default.voice.type"),
WEBAPP_ADMIN_USERNAME("webapp.admin.username"),
WEBAPP_ADMIN_PASSWORD("webapp.admin.password"),
WEBAPP_VIEWER_USERNAME("webapp.viewer.username"),

View File

@@ -44,8 +44,8 @@ import java.nio.file.Files
import java.time.LocalDateTime
import codes.configKeys
import org.tinylog.Logger
//import com.sun.security.auth.login.ConfigFile
import java.io.File
import java.nio.file.Path
@Suppress("unused")
@@ -64,7 +64,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
}
fun Start() {
Logger.info { "Starting Web Application on port $listenPort" }
app = Javalin.create { config ->
config.useVirtualThreads = true
config.staticFiles.add("/webpage")
@@ -191,8 +191,6 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
}
}
}
}
path("soundbank.html") {
@@ -213,6 +211,27 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
path("timer.html") {
before { CheckUsers(it) }
}
path("filemanagement.html") {
before { CheckUsers(it) }
}
path("broadcastzones.html") {
before { CheckUsers(it) }
}
path("overview.html") {
before { CheckUsers(it) }
}
path("setting.html"){
before { CheckUsers(it) }
}
path("streamerstatus.html"){
before { CheckUsers(it) }
}
path("timer.html"){
before { CheckUsers(it) }
}
path("usermanagement.html"){
before { CheckUsers(it) }
}
path("api") {
path("VoiceType") {
get {
@@ -315,7 +334,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
VoiceType.valueOf(addvalue.VoiceType),
Category.valueOf(addvalue.Category)
).resolve(addvalue.Path)
if (Files.isRegularFile(absolutepath)) {
if (ValidFile(absolutepath)) {
addvalue.Path = absolutepath.toAbsolutePath().toString()
if (db.soundDB.Add(addvalue)) {
db.soundDB.Resort()
@@ -348,7 +367,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.soundDB.DeleteByIndex(index.toInt())) {
db.soundDB.Resort()
@@ -414,7 +434,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
newsb.VoiceType,
newsb.Category
).resolve(newsb.Path)
if (Files.isRegularFile(newpath)) {
if (ValidFile(newpath)) {
if (newpath.toAbsolutePath().toString() != sb.Path) {
sb.Path = newpath.toAbsolutePath().toString()
varchanged = true
@@ -550,7 +570,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.messageDB.DeleteByIndex(index.toInt())) {
db.messageDB.Resort()
@@ -566,7 +587,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// update messagebank by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
val mb = db.messageDB.List.find { xx -> xx.index == index }
if (mb == null) {
@@ -677,7 +699,14 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val tag = json.get("tag").asText("")
val languages = json.get("language").asText("").split(";")
if (ValidString(tag)) {
if (languages.all { xx -> Language.entries.any { yy -> yy.name.equals(xx, true) } }) {
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)) {
@@ -714,7 +743,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.languageDB.DeleteByIndex(index.toInt())) {
db.languageDB.Resort()
@@ -730,7 +760,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// update by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
val ll = db.languageDB.List.find { xx -> xx.index == index }
if (ll == null) {
@@ -865,7 +896,11 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
)
)
} else it.status(500)
.result(objectmapper.writeValueAsString(resultMessage("Failed to add schedule to database")))
.result(
objectmapper.writeValueAsString(
resultMessage("Failed to add schedule to database")
)
)
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid Language")))
} else it.status(400)
@@ -887,7 +922,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.scheduleDB.DeleteByIndex(index.toInt())) {
db.scheduleDB.Resort()
@@ -902,9 +938,9 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
patch("UpdateByIndex/{index}") {
// update by index
val index = it.pathParam("index").toUIntOrNull()
if (index!=null){
if (index != null) {
val sb = db.scheduleDB.List.find { xx -> xx.index == index }
if (sb!=null){
if (sb != null) {
val json = objectmapper.readTree(it.body())
val _description = json.get("Description").asText("")
val _time = json.get("Time").asText("")
@@ -914,18 +950,33 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val _enable = json.get("Enable").asBoolean()
val _broadcast_zones = json.get("BroadcastZones").asText("")
val _language = json.get("Language").asText("")
val newsb = ScheduleBank(index, _description, _day, _time, _soundpath, _repeat, _enable, _broadcast_zones, _language)
if (newsb.isNotEmpty()){
if (!sb.isEqual(newsb)){
if (db.scheduleDB.UpdateByIndex(index.toInt(), newsb)){
val newsb = ScheduleBank(
index,
_description,
_day,
_time,
_soundpath,
_repeat,
_enable,
_broadcast_zones,
_language
)
if (newsb.isNotEmpty()) {
if (!sb.isEqual(newsb)) {
if (db.scheduleDB.UpdateByIndex(index.toInt(), newsb)) {
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")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Some fields are empty")))
} 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")))
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Some fields are empty")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Schedule with index $index not found")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Schedule with index $index not found")))
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
}
get("ExportXLSX") {
val xlsxdata = db.scheduleDB.Export_XLSX()
@@ -967,7 +1018,11 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
get("GetMessageAndBroadcastZones") {
val result = object {
val messages = db.messageDB.List
.filter { mb -> !mb.Message_Detail.contains("[") && !mb.Message_Detail.contains("]") }
.filter { mb ->
!mb.Message_Detail.contains("[") && !mb.Message_Detail.contains(
"]"
)
}
.map { mb -> "${mb.Description} [${mb.ANN_ID}]" }
val broadcastzones = db.broadcastDB.List
}
@@ -1072,7 +1127,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.userDB.DeleteByIndex(index.toInt())) {
db.userDB.Resort()
@@ -1120,7 +1176,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val atags = _airline_tags.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct()
val ctags =
_city_tags.split(";").map { it.trim() }.filter { it.isNotEmpty() }
_city_tags.split(";").map { it.trim() }
.filter { it.isNotEmpty() }
.distinct()
val msgids = _messagebank_ann_id.split(";").map { it.trim() }
.filter { it.isNotEmpty() }.distinct()
@@ -1160,13 +1217,19 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
)
} else ctx.status(500).result(
objectmapper.writeValueAsString(resultMessage("Failed to update user with index $index"))
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")))
.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)
@@ -1307,7 +1370,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
if (ValidString(_soundchannel)) {
if (ValidString(_box)) {
if (ValidString(_relay)) {
val newbp = BroadcastZones(0u, _description, _soundchannel, _box, _relay)
val newbp =
BroadcastZones(0u, _description, _soundchannel, _box, _relay)
if (db.broadcastDB.Add(newbp)) {
db.broadcastDB.Resort()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
@@ -1326,7 +1390,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.broadcastDB.DeleteByIndex(index.toInt())) {
db.broadcastDB.Resort()
@@ -1342,7 +1407,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// update by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
val bz = db.broadcastDB.List.find { xx -> xx.index == index }
if (bz == null) {
@@ -1448,7 +1514,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
val sc = db.soundchannelDB.List.find { xx -> xx.index == index }
if (sc == null) {
@@ -1471,8 +1538,9 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} 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 }
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")))
@@ -1481,10 +1549,20 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val newsc = SoundChannel(0u, _channel, _ip)
if (db.soundchannelDB.UpdateByIndex(index.toInt(), newsc)) {
db.soundchannelDB.Resort()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
it.result(
objectmapper.writeValueAsString(
resultMessage(
"OK"
)
)
)
} else {
it.status(500)
.result(objectmapper.writeValueAsString(resultMessage("Failed to update sound channel with index $index")))
.result(
objectmapper.writeValueAsString(
resultMessage("Failed to update sound channel with index $index")
)
)
}
}
@@ -1563,7 +1641,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.queuepagingDB.DeleteByIndex(index.toInt())) {
db.queuepagingDB.Resort()
@@ -1577,7 +1656,6 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
}
}
path("QueueTable") {
get("List") {
it.result(MariaDB.ArrayListtoString(db.queuetableDB.List))
@@ -1596,7 +1674,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.queuetableDB.DeleteByIndex(index.toInt())) {
db.queuetableDB.Resort()
@@ -1610,8 +1689,190 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
}
}
}
path("Settings") {
path("FileManager") {
get("PagingResultList") {
it.result(objectmapper.writeValueAsString(ListAudioFiles(Somecodes.PagingResult_directory)))
}
delete("DeleteOldPagingResultFiles/{days}") {
// kalau tidak ada, default 7 hari
val days = it.pathParam("days").toIntOrNull() ?: 7
Somecodes.Delete_Old_PagingResult_Files(days) { success, failed ->
it.result(objectmapper.writeValueAsString(resultMessage("Old paging result files deleted. Deleted: $success, Failed: $failed")))
}
}
delete("ClearPagingResultFiles") {
Somecodes.Clear_PagingResult_Directory { success, failed ->
it.result(objectmapper.writeValueAsString(resultMessage("Paging result files cleared. Deleted: $success, Failed: $failed")))
}
}
post("DownloadPagingResultFile") {
val json: JsonNode = objectmapper.readTree(it.body())
val filename = json.get("filename").asText("")
if (filename.isNotEmpty()) {
val p: Path = Somecodes.PagingResult_directory.resolve(filename)
if (ValidFile(p)) {
it.header("Content-Disposition", "attachment; filename=\"$filename\"")
it.outputStream().use { out ->
Files.newInputStream(p).use { inp ->
inp.copyTo(out)
}
}
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("File not found")))
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Filename is empty")))
}
get("SoundbankResultList") {
it.result(objectmapper.writeValueAsString(ListAudioFiles(Somecodes.SoundbankResult_directory)))
}
delete("DeleteOldSoundbankResultFiles/{days}") {
// kalau tidak ada, default 7 hari
val days = it.pathParam("days").toIntOrNull() ?: 7
Somecodes.Delete_Old_SoundbankResult_Files(days) { success, failed ->
it.result(objectmapper.writeValueAsString(resultMessage("Old soundbank result files deleted. Deleted: $success, Failed: $failed")))
}
}
delete("ClearSoundbankResultFiles") {
Somecodes.Clear_PagingResult_Directory { success, failed ->
it.result(objectmapper.writeValueAsString(resultMessage("Soundbank result files cleared. Deleted: $success, Failed: $failed")))
}
}
post("DownloadSoundbankResultFile") {
val json: JsonNode = objectmapper.readTree(it.body())
val filename = json.get("filename").asText("")
if (filename.isNotEmpty()) {
val p: Path = Somecodes.SoundbankResult_directory.resolve(filename)
if (ValidFile(p)) {
it.header("Content-Disposition", "attachment; filename=\"$filename\"")
it.outputStream().use { out ->
Files.newInputStream(p).use { inp ->
inp.copyTo(out)
}
}
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("File not found")))
} else it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Filename is empty")))
}
get("ListSoundbank/{language}/{voice}/{category}"){
val language = it.pathParam("language")
val voice = it.pathParam("voice")
val category = it.pathParam("category")
//println("ListSoundbank called with language=$language, voice=$voice, category=$category")
if (ValidString(language) && Language.entries.any { lang -> lang.name == language }) {
if (ValidString(voice) && VoiceType.entries.any { vtype -> vtype.name == voice }) {
if (ValidString(category) && Category.entries.any { cat -> cat.name == category }) {
val targetdir = Somecodes.SoundbankDirectory(
Language.valueOf(language),
VoiceType.valueOf(voice),
Category.valueOf(category)
)
val result = ListAudioFiles(targetdir).map{ mm ->
// just the filename, without path
mm.substring(mm.lastIndexOf(File.separator)+1)
}
//println("ListSoundbank result: $result")
it.result(objectmapper.writeValueAsString(result))
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Category parameter is invalid")))
}
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("VoiceType parameter is invalid")))
}
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Language parameter is invalid")))
}
}
// tested ok
post("UploadSoundbank/{language}/{voice}/{category}") {
val language = it.pathParam("language")
val voice = it.pathParam("voice")
val category = it.pathParam("category")
val uploaded = it.uploadedFiles()
if (ValidString(language) && Language.entries.any { lang -> lang.name == language }) {
if (ValidString(voice) && VoiceType.entries.any { vtype -> vtype.name == voice }) {
if (ValidString(category) && Category.entries.any { cat -> cat.name == category }) {
if (uploaded.isNotEmpty()) {
val targetdir = Somecodes.SoundbankDirectory(
Language.valueOf(language),
VoiceType.valueOf(voice),
Category.valueOf(category)
)
if (!Files.isDirectory(targetdir)) Files.createDirectories(targetdir)
val successfiles = mutableListOf<String>()
val failedfiles = mutableListOf<String>()
val alreadyexists = mutableListOf<String>()
uploaded.forEach { ff ->
val targetfile = targetdir.resolve(ff.filename())
if (Files.exists(targetfile)) {
alreadyexists.add(ff.filename())
} else {
try {
Files.newOutputStream(targetfile).use { out ->
ff.content().use { inp ->
inp.copyTo(out)
}
}
Logger.info { "Uploaded soundbank file to ${targetfile.toAbsolutePath()}" }
successfiles.add(ff.filename())
} catch (e: Exception) {
Logger.error {
"Failed to upload soundbank file to ${targetfile.toAbsolutePath()}: ${e.message}"
}
failedfiles.add(ff.filename())
}
}
}
if (successfiles.size == uploaded.size) {
it.result(
objectmapper.writeValueAsString(
resultMessage(
"All files uploaded successfully: ${
successfiles.joinToString(
", "
)
}"
)
)
)
} else {
it.result(
objectmapper.writeValueAsString(
resultMessage(
"Some files uploaded successfully: ${
successfiles.joinToString(
", "
)
}, failed: ${failedfiles.joinToString(", ")}, already exists: ${alreadyexists.joinToString(", ")}"
)
)
)
}
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("No file uploaded")))
}
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Category parameter is invalid")))
}
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("VoiceType parameter is invalid")))
}
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Language parameter is invalid")))
}
}
}
path("Settings") {
get("SoundbankDirectory") {
val dir = _config.Get(configKeys.SOUNDBANK_DIRECTORY.key)
it.result(objectmapper.writeValueAsString(resultMessage(dir)))
@@ -1629,165 +1890,71 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
.result(objectmapper.writeValueAsString(resultMessage("Invalid directory value")))
}
}
get("SoundbankResultList") {
it.result(objectmapper.writeValueAsString(ListAudioFiles(Somecodes.SoundbankResult_directory)))
}
get("SoundbankResultFile/{filename}") {
//TODO recheck bener/gak cara downloadnya
val filename = it.pathParam("filename")
val filepath = Somecodes.SoundbankResult_directory.resolve(filename)
if (ValidFile(filename) && Files.isRegularFile(filepath)) {
it.header(
"Content-Disposition",
"attachment; filename=\"$filename\""
)
it.outputStream().use { out ->
Files.newInputStream(filepath).use { inp ->
inp.copyTo(out)
}
}
} else {
it.status(404).result(objectmapper.writeValueAsString(resultMessage("File not found")))
}
}
get("PagingResultList") {
it.result(objectmapper.writeValueAsString(ListAudioFiles(Somecodes.PagingResult_directory)))
}
get("PagingResultFile/{filename}") {
val filename = it.pathParam("filename")
val filepath = Somecodes.PagingResult_directory.resolve(filename)
if (ValidFile(filename) && Files.isRegularFile(filepath)) {
it.header("Content-Disposition", "attachment; filename=\"$filename\"")
it.outputStream().use { out ->
Files.newInputStream(filepath).use { inp ->
inp.copyTo(out)
}
}
} else {
it.status(404).result(objectmapper.writeValueAsString(resultMessage("File not found")))
}
}
get("FISCode") {
//TODO get FIS code
val value = object {
//get from config file
val GOP = _config.Get(configKeys.REMARK_GOP.key)
val GBD = _config.Get(configKeys.REMARK_GBD.key)
val GFC = _config.Get(configKeys.REMARK_GFC.key)
val FLD = _config.Get(configKeys.REMARK_FLD.key)
val defaultvoice = _config.Get(configKeys.DEFAULT_VOICE_TYPE.key)
}
//println("Serving FIS Code request: GOP=${value.GOP}, GBD=${value.GBD}, GFC=${value.GFC}, FLD=${value.FLD}, DefaultVoice=${value.defaultvoice}")
it.result(objectmapper.writeValueAsString(value))
}
post("FISCode") {
//TODO set FIS code
val json: JsonNode = objectmapper.readTree(it.body())
val _gop = json.get("GOP").asText("")
val _gbd = json.get("GBD").asText("")
val _gfc = json.get("GFC").asText("")
val _fld = json.get("FLD").asText("")
val defaultvoice = json.get("defaultvoice").asText("")
//println("Received FIS Code update: GOP=$_gop, GBD=$_gbd, GFC=$_gfc, FLD=$_fld, DefaultVoice=$defaultvoice")
if (ValidString(_gop) && ValidString(_gbd) && ValidString(_gfc) && ValidString(_fld)) {
// save to config file
_config.Set(configKeys.REMARK_GOP.key, _gop)
_config.Set(configKeys.REMARK_GBD.key, _gbd)
_config.Set(configKeys.REMARK_GFC.key, _gfc)
_config.Set(configKeys.REMARK_FLD.key, _fld)
_config.Set(configKeys.DEFAULT_VOICE_TYPE.key, defaultvoice)
_config.Save()
Logger.info { "Changed FIS Codes" }
db.Add_Log("AAS", "Save FIS Codes Message: GOP=$_gop, GBD=$_gbd, GFC=$_gfc, FLD=$_fld")
db.Add_Log(
"AAS",
"Save FIS Codes Message: GOP=$_gop, GBD=$_gbd, GFC=$_gfc, FLD=$_fld"
)
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid FIS code value")))
}
}
post("UploadSoundbank/{language}/{voice}/{category}") {
val language = it.pathParam("language")
val voice = it.pathParam("voice")
val category = it.pathParam("category")
val uploaded = it.uploadedFiles()
if (ValidString(language) && Language.entries.any{ lang -> lang.name == language}) {
if (ValidString(voice) && VoiceType.entries.any{ vtype -> vtype.name == voice}) {
if (ValidString(category) && Category.entries.any{ cat -> cat.name == category}) {
if (uploaded.isNotEmpty()) {
val targetdir = Somecodes.SoundbankDirectory(
Language.valueOf(language),
VoiceType.valueOf(voice),
Category.valueOf(category)
)
if (!Files.isDirectory(targetdir)) Files.createDirectories(targetdir)
val successfiles = mutableListOf<String>()
val failedfiles = mutableListOf<String>()
uploaded.forEach { ff ->
val targetfile = targetdir.resolve(ff.filename())
try {
Files.newOutputStream(targetfile).use { out ->
ff.content().use { inp ->
inp.copyTo(out)
}
}
Logger.info { "Uploaded soundbank file to ${targetfile.toAbsolutePath()}" }
successfiles.add(ff.filename())
} catch (e: Exception) {
Logger.error {
"Failed to upload soundbank file to ${targetfile.toAbsolutePath()}: ${e.message}"
}
failedfiles.add(ff.filename())
}
}
if (successfiles.size==uploaded.size){
it.result(objectmapper.writeValueAsString(resultMessage("All files uploaded successfully: ${successfiles.joinToString(", ")}")))
} else {
it.result(objectmapper.writeValueAsString(resultMessage("Some files uploaded successfully: ${successfiles.joinToString(", ")}, failed: ${failedfiles.joinToString(", ")}")))
}
} else {
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("No file uploaded")))
}
} else {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Category parameter is invalid")))
}
} else {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("VoiceType parameter is invalid")))
}
} else {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Language parameter is invalid")))
}
}
}
}
}
}.start(listenPort)
}.start(listenPort)
}
fun CheckUsers(ctx: Context) {
//val user = ctx.sessionAttribute<String?>("user")
val user = ctx.cookie("aas-user")
if (user == null) {
ctx.redirect("login.html")
}
fun CheckUsers(ctx: Context) {
//val user = ctx.sessionAttribute<String?>("user")
val user = ctx.cookie("aas-user")
if (user == null) {
ctx.redirect("login.html")
}
val foundUser = userlist.find { it.first == user }
if (foundUser == null) {
ctx.redirect("login.html")
}
val foundUser = userlist.find { it.first == user }
if (foundUser == null) {
ctx.redirect("login.html")
}
}
fun Stop() {
app?.stop()
fun Stop() {
app?.stop()
}
}
}