commit 13/02/2026

This commit is contained in:
2026-02-13 17:04:20 +07:00
parent c797c6e7fe
commit 7b4420ddbd
10 changed files with 365 additions and 198 deletions

View File

@@ -16,10 +16,13 @@ import content.Language
import content.VoiceType
import database.data.Log
import database.MariaDB
import database.data.QueueTable
import database.table.Table_Adzan
import database.table.Table_BroadcastZones
import database.table.Table_Logs
import database.table.Table_Messagebank
import database.table.Table_QueuePaging
import database.table.Table_QueueSoundbank
import database.table.Table_SoundChannel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -55,6 +58,8 @@ val apptick : Long = System.currentTimeMillis()
lateinit var broadcastDB: Table_BroadcastZones
lateinit var soundchannelDB: Table_SoundChannel
lateinit var messageDB: Table_Messagebank
lateinit var queuetableDB: Table_QueueSoundbank
lateinit var queuepagingDB: Table_QueuePaging
lateinit var logDB: Table_Logs
lateinit var adzanTable : Table_Adzan
@@ -182,6 +187,7 @@ fun main(args: Array<String>) {
longitude = config.Get(configKeys.LONGITUDE.key).toDouble(),
timezone = TimeZone.getTimeZone(config.Get(configKeys.TIMEZONE.key))
)
adzanTable.GetTodayPrayerTimes()
val subcode01 = MainExtension01()
@@ -190,18 +196,35 @@ fun main(args: Array<String>) {
CoroutineScope(Dispatchers.Default).launch {
while (isActive) {
delay(1000)
adzanTable.CheckTime()?.let{ adz ->
Logger.info { "It's time for Adzan ${adz.prayerName} at ${adz.timeString}" }
val qt = QueueTable(
Source = "AAS",
Type = "ADZAN",
Message = adz.message,
Language = adzanTable.adzan_language,
SB_TAGS = adz.sb_tags,
BroadcastZones = adzanTable.adzan_broadcastzones
)
queuetableDB.Add(qt)
}
// prioritas 1 , habisin queue paging
if (subcode01.Read_Queue_Paging()){
// processing paging, skip selanjutnya
delay(2000)
continue
}
// prioritas 2, habisin queue shalat
if (subcode01.Read_Queue_Shalat()){
// processing shalat, skip selanjutnya
delay(2000)
continue
}
// // prioritas 2, habisin queue shalat
// if (subcode01.Read_Queue_Shalat()){
// // processing shalat, skip selanjutnya
// delay(2000)
// continue
// }
// prioritas 3, habisin queue timer
if (subcode01.Read_Queue_Timer()){
// processing timer, skip selanjutnya

View File

@@ -9,7 +9,6 @@ import codes.Somecodes.Companion.SoundbankResult_directory
import codes.Somecodes.Companion.ValidFile
import codes.Somecodes.Companion.ValidString
import codes.Somecodes.Companion.dateformat1
import codes.Somecodes.Companion.datetimeformat1
import codes.Somecodes.Companion.timeformat2
import codes.configKeys
import content.Category
@@ -22,7 +21,6 @@ import database.data.Soundbank
import org.tinylog.Logger
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
/**
@@ -676,8 +674,8 @@ class MainExtension01 {
* @return true if a paging job is processed and started streaming, false otherwise
*/
fun Read_Queue_Paging(): Boolean {
db.queuepagingDB.Get()
val qp = db.queuepagingDB.List.firstOrNull { it.Type.equals("PAGING", true) }
queuepagingDB.Get()
val qp = queuepagingDB.List.firstOrNull { it.Type.equals("PAGING", true) }
if (qp == null) return false
try {
if (!ValidFile(qp.Message)) throw Exception("Invalid audio file ${qp.Message}")
@@ -722,14 +720,14 @@ class MainExtension01 {
"Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}"
Logger.info { logmessage }
logDB.Add("AAS", logmessage)
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
db.queuepagingDB.Resort()
queuepagingDB.DeleteByIndex(qp.index.toInt())
queuepagingDB.Resort()
return true
} else throw Exception("Audio file ${qp.Message} is not valid")
}
} catch (e: Exception) {
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
db.queuepagingDB.Resort()
queuepagingDB.DeleteByIndex(qp.index.toInt())
queuepagingDB.Resort()
val msg = "Canceled paging message $qp due to exception: ${e.message}"
logDB.Add("AAS", msg)
Logger.error { msg }
@@ -742,8 +740,8 @@ class MainExtension01 {
* @return true if a shalat job is processed and started streaming, false otherwise
*/
fun Read_Queue_Shalat(): Boolean {
db.queuepagingDB.Get()
val qp = db.queuepagingDB.List.firstOrNull { it.Type.equals("SHALAT", true) }
queuepagingDB.Get()
val qp = queuepagingDB.List.firstOrNull { it.Type.equals("SHALAT", true) }
if (qp == null) return false
try {
val ann_id = Get_ANN_ID(qp.Message)
@@ -829,14 +827,14 @@ class MainExtension01 {
"Broadcast started SHALAT message with generated file '$targetfile' to zones: ${qp.BroadcastZones}"
Logger.info { logmsg }
logDB.Add("AAS", logmsg)
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
db.queuepagingDB.Resort()
queuepagingDB.DeleteByIndex(qp.index.toInt())
queuepagingDB.Resort()
return true
}
} catch (e: Exception) {
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
db.queuepagingDB.Resort()
queuepagingDB.DeleteByIndex(qp.index.toInt())
queuepagingDB.Resort()
val msg = "Canceled shalat message $qp due to exception: ${e.message}"
logDB.Add("AAS", msg)
Logger.error { msg }
@@ -849,8 +847,8 @@ class MainExtension01 {
* @return true if a timer job is processed and started streaming, false otherwise
*/
fun Read_Queue_Timer(): Boolean {
db.queuetableDB.Get()
val qa = db.queuetableDB.List.firstOrNull { it.Type.equals("TIMER", true) }
queuetableDB.Get()
val qa = queuetableDB.List.firstOrNull { it.Type.equals("TIMER", true) }
if (qa == null) return false
try {
val ann_id = Get_ANN_ID(qa.SB_TAGS)
@@ -928,14 +926,14 @@ class MainExtension01 {
"Broadcast started TIMER message with generated file '$targetfile' to zones: ${qa.BroadcastZones}"
Logger.info { logmsg }
logDB.Add("AAS", logmsg)
db.queuetableDB.DeleteByIndex(qa.index.toInt())
db.queuetableDB.Resort()
queuetableDB.DeleteByIndex(qa.index.toInt())
queuetableDB.Resort()
return true
}
} catch (e: Exception) {
db.queuetableDB.DeleteByIndex(qa.index.toInt())
db.queuetableDB.Resort()
queuetableDB.DeleteByIndex(qa.index.toInt())
queuetableDB.Resort()
val msg = "Canceled TIMER message $qa due to exception: ${e.message}"
logDB.Add("AAS", msg)
Logger.error { msg }
@@ -949,8 +947,8 @@ class MainExtension01 {
* @return true if a soundbank job is processed and started streaming, false otherwise
*/
fun Read_Queue_Soundbank(): Boolean {
db.queuetableDB.Get()
val qa = db.queuetableDB.List.firstOrNull { it.Type.equals("SOUNDBANK", true) }
queuetableDB.Get()
val qa = queuetableDB.List.firstOrNull { it.Type.equals("SOUNDBANK", true) }
if (qa == null) return false
//println("Processing $qa")
try {
@@ -1084,8 +1082,8 @@ class MainExtension01 {
"Broadcast started SOUNDBANK message with generated file '$targetfile' to zones: ${qa.BroadcastZones}"
Logger.info { logmsg }
logDB.Add("AAS", logmsg)
db.queuetableDB.DeleteByIndex(qa.index.toInt())
db.queuetableDB.Resort()
queuetableDB.DeleteByIndex(qa.index.toInt())
queuetableDB.Resort()
return true
}
@@ -1094,8 +1092,8 @@ class MainExtension01 {
val msg = "Canceled SOUNDBANK message $qa due to exception: ${e.message}"
logDB.Add("AAS", msg)
Logger.error { msg }
db.queuetableDB.DeleteByIndex(qa.index.toInt())
db.queuetableDB.Resort()
queuetableDB.DeleteByIndex(qa.index.toInt())
queuetableDB.Resort()
}
return false
}
@@ -1125,17 +1123,14 @@ class MainExtension01 {
}
if (specialdate != null) {
val qt = QueueTable(
0u,
LocalDateTime.now().format(datetimeformat1),
"AAS",
"TIMER",
specialdate.Description,
specialdate.Soundpath,
specialdate.BroadcastZones,
1.toUInt(),
specialdate.Language
Source="AAS",
Type="TIMER",
Message=specialdate.Description,
SB_TAGS = specialdate.Soundpath,
BroadcastZones = specialdate.BroadcastZones,
Language = specialdate.Language
)
db.queuetableDB.Add(qt)
queuetableDB.Add(qt)
return
}
@@ -1153,17 +1148,14 @@ class MainExtension01 {
}
if (weekly != null) {
val qt = QueueTable(
0u,
LocalDateTime.now().format(datetimeformat1),
"AAS",
"TIMER",
weekly.Description,
weekly.Soundpath,
weekly.BroadcastZones,
1.toUInt(),
weekly.Language
Source="AAS",
Type="TIMER",
Message=weekly.Description,
SB_TAGS = weekly.Soundpath,
BroadcastZones = weekly.BroadcastZones,
Language = weekly.Language
)
db.queuetableDB.Add(qt)
queuetableDB.Add(qt)
return
}
@@ -1173,17 +1165,14 @@ class MainExtension01 {
}
if (daily != null) {
val qt = QueueTable(
0u,
LocalDateTime.now().format(datetimeformat1),
"AAS",
"TIMER",
daily.Description,
daily.Soundpath,
daily.BroadcastZones,
1.toUInt(),
daily.Language
Source="AAS",
Type="TIMER",
Message = daily.Description,
SB_TAGS = daily.Soundpath,
BroadcastZones = daily.BroadcastZones,
Language = daily.Language
)
db.queuetableDB.Add(qt)
queuetableDB.Add(qt)
return
}

View File

@@ -710,7 +710,13 @@ class Somecodes {
return false
}
/**
* Get a list of all available time zones.
* @return A list of strings representing the available time zones.
*/
fun Get_TimeZones() : List<String>{
return ZoneId.getAvailableZoneIds().sorted()
}
/**
* Find a schedule day by its name.

View File

@@ -17,6 +17,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import messageDB
import org.tinylog.Logger
import queuepagingDB
import queuetableDB
import tcpreceiver
import udpreceiver
import java.net.ServerSocket
@@ -234,8 +236,8 @@ class TCP_Android_Command_Server {
pj.broadcastzones
)
Logger.info{"Inserting paging audio to queue paging table from Android $key, data=$qp"}
if (db.queuepagingDB.Add(qp)) {
db.queuepagingDB.Resort()
if (queuepagingDB.Add(qp)) {
queuepagingDB.Resort()
logcb.accept("Paging audio inserted to queue paging table from Android $key, file ${pj.filePath.absolutePathString()}")
cb.accept("PCMFILE_STOP;OK@")
return
@@ -289,8 +291,8 @@ class TCP_Android_Command_Server {
pj.filePath.absolutePathString(),
pj.broadcastzones
)
if (db.queuepagingDB.Add(qp)){
db.queuepagingDB.Resort()
if (queuepagingDB.Add(qp)){
queuepagingDB.Resort()
logcb.accept("Paging audio inserted to queue paging table from IPM $key, file ${pj.filePath.absolutePathString()}")
cb.accept("STOPPAGINGAND;OK@")
return
@@ -579,18 +581,15 @@ class TCP_Android_Command_Server {
if (ValidString(tags)){
if (ValidString(zone)){
val qt = QueueTable(
0u,
LocalDateTime.now().format(datetimeformat1),
"ANDROID",
"SOUNDBANK",
desc,
tags,
zone,
1u,
lang
Source="ANDROID",
Type="SOUNDBANK",
Message=desc,
SB_TAGS = tags,
BroadcastZones = zone,
Language = lang
)
if (db.queuetableDB.Add(qt)){
db.queuetableDB.Resort()
if (queuetableDB.Add(qt)){
queuetableDB.Resort()
logcb.accept("Broadcast request from Android $key username=${listUserLogin.find { it.ip==key }?.username ?: "UNKNOWN"} inserted. Message: $desc;$lang;$tags;$zone")
cb.accept("BROADCASTAND;OK@")
return

View File

@@ -24,6 +24,8 @@ import database.table.Table_Users
import messageDB
import broadcastDB
import logDB
import queuepagingDB
import queuetableDB
import soundchannelDB
class MariaDB {
@@ -32,8 +34,7 @@ class MariaDB {
lateinit var soundDB: Table_Soundbank
lateinit var languageDB: Table_LanguageLink
lateinit var scheduleDB: Table_Schedule
lateinit var queuetableDB: Table_QueueSoundbank
lateinit var queuepagingDB: Table_QueuePaging
lateinit var userDB: Table_Users

View File

@@ -4,7 +4,7 @@ import codes.Somecodes.Companion.datetimeformat1
import java.time.Duration
import java.time.LocalDateTime
data class QueueTable(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var SB_TAGS: String, var BroadcastZones: String, var Repeat: UInt, var Language: String){
data class QueueTable(var index: UInt=0u, var Date_Time: String =LocalDateTime.now().format(datetimeformat1), var Source: String, var Type: String, var Message: String, var SB_TAGS: String, var BroadcastZones: String, var Repeat: UInt=1u, var Language: String){
/**
* Check if all fields are not empty

View File

@@ -1,12 +1,17 @@
package database.table
import codes.Somecodes.Companion.timeformat2
import com.batoulapps.adhan.CalculationMethod
import com.batoulapps.adhan.CalculationParameters
import com.batoulapps.adhan.Coordinates
import com.batoulapps.adhan.Madhab
import com.batoulapps.adhan.PrayerTimes
import com.batoulapps.adhan.data.DateComponents
import content.Language
import messageDB
import org.tinylog.Logger
import java.text.SimpleDateFormat
import java.time.LocalTime
import java.util.Date
import java.util.TimeZone
@@ -16,7 +21,6 @@ import java.util.TimeZone
* @param longitude The longitude of the location. Default is Monas, Jakarta (longitude: 106.8272).
* @param timezone The time zone for formatting prayer times. Default is "Asia/Jakarta".
*/
@Suppress("unused")
class Table_Adzan(val latitude: Double = -6.1751, val longitude: Double = 106.8272, val timezone : TimeZone = TimeZone.getTimeZone("Asia/Jakarta")) {
var coordinate: Coordinates = Coordinates(latitude, longitude)
@@ -30,11 +34,21 @@ class Table_Adzan(val latitude: Double = -6.1751, val longitude: Double = 106.82
var maghrib_enable = false
var isya_enable = false
var fajar_sound = ""
var dzuhur_sound = ""
var ashar_sound = ""
var maghrib_sound = ""
var isya_sound = ""
var fajar_message = ""
var dzuhur_message = ""
var ashar_message = ""
var maghrib_message = ""
var isya_message = ""
var fajar_time = ""
var dzuhur_time = ""
var ashar_time = ""
var maghrib_time = ""
var isya_time = ""
var adzan_broadcastzones = ""
var adzan_language = Language.DEFAULT.value
init{
// sumber chatgpt Kemenag
@@ -44,14 +58,93 @@ class Table_Adzan(val latitude: Double = -6.1751, val longitude: Double = 106.82
timeformatter.timeZone = timezone
}
/**
* Change the time zone used for formatting prayer times.
* @param timezone The new AdzanTimeZone.
*/
fun ChangeTimezone(timezone: AdzanTimeZone) {
ChangeTimeZone(timezone.toTimeZoneString())
data class AdzanTask(
val prayerName : String,
val timeString : String,
val message : String,
val sb_tags : String
)
fun CheckTime() : AdzanTask?{
val hhmm = LocalTime.now().format(timeformat2)
if (hhmm == fajar_time){
if (fajar_enable){
val mb = messageDB.Find_Messagebank(fajar_message, adzan_language)
if (mb!=null){
return AdzanTask(
"Fajar",
fajar_time,
mb.Description,
mb.Message_TAGS
)
} else Logger.error { "Skipped Adzan Fajar because Unable to find $fajar_message in messageDB" }
} else Logger.info{"Skipped Adzan Fajar because fajr_enable is false"}
}
if (hhmm == dzuhur_time){
if (dzuhur_enable){
val mb = messageDB.Find_Messagebank(dzuhur_message, adzan_language)
if (mb!=null){
return AdzanTask(
"Dzuhur",
dzuhur_time,
mb.Description,
mb.Message_TAGS
)
} else Logger.error { "Skipped Adzan Dzuhur because Unable to find $dzuhur_message in messageDB" }
} else Logger.info{"Skipped Adzan Dzuhur because dzuhur_enable is false"}
}
if (hhmm == ashar_time) {
if (ashar_enable){
val mb = messageDB.Find_Messagebank(ashar_message, adzan_language)
if (mb!=null){
return AdzanTask(
"Ashar",
ashar_time,
mb.Description,
mb.Message_TAGS
)
} else Logger.error { "Skipped Adzan Ashar because Unable to find $ashar_message in messageDB" }
} else Logger.info{"Skipped Adzan Ashar because ashar_enable is false"}
}
if (hhmm == maghrib_time){
if (maghrib_enable){
val mb = messageDB.Find_Messagebank(maghrib_message, adzan_language)
if (mb!=null){
return AdzanTask(
"Maghrib",
maghrib_time,
mb.Description,
mb.Message_TAGS
)
} else Logger.error { "Skipped Adzan Maghrib because Unable to find $maghrib_message in messageDB" }
} else Logger.info{"Skipped Adzan Maghrib because maghrib_enable is false"}
}
if (hhmm == isya_time) {
if (isya_enable){
val mb = messageDB.Find_Messagebank(isya_message, adzan_language)
if (mb!=null){
return AdzanTask(
"Isya",
isya_time,
mb.Description,
mb.Message_TAGS
)
} else Logger.error { "Skipped Adzan Isya because Unable to find $isya_message in messageDB" }
} else Logger.info{"Skipped Adzan Isya because isya_enable is false"}
}
return null
}
// /**
// * Change the time zone used for formatting prayer times.
// * @param timezone The new AdzanTimeZone.
// */
// fun ChangeTimezone(timezone: AdzanTimeZone) {
// ChangeTimeZone(timezone.toTimeZoneString())
// }
/**
* Change the time zone used for formatting prayer times.
* @param timezoneString The new time zone string (e.g., "Asia/Jakarta").
@@ -60,29 +153,29 @@ class Table_Adzan(val latitude: Double = -6.1751, val longitude: Double = 106.82
timeformatter.timeZone = TimeZone.getTimeZone(timezoneString)
}
/**
* Set prayer time adjustments in minutes.
* @param fajrMinute Adjustment for Fajr prayer time in minutes.
* @param dhuhrMinute Adjustment for Dhuhr prayer time in minutes.
* @param asrMinute Adjustment for Asr prayer time in minutes.
* @param maghribMinute Adjustment for Maghrib prayer time in minutes.
* @param ishaMinute Adjustment for Isha prayer time in minutes.
*/
fun SetPrayerAdjustment(fajrMinute: Int = 0, dhuhrMinute: Int = 0, asrMinute: Int = 0,maghribMinute: Int = 0, ishaMinute: Int = 0) {
params.adjustments.fajr = fajrMinute
params.adjustments.dhuhr = dhuhrMinute
params.adjustments.asr = asrMinute
params.adjustments.maghrib = maghribMinute
params.adjustments.isha = ishaMinute
}
/**
* Change the coordinates used for Adzan calculations.
* @param lat The new latitude.
* @param long The new longitude.
*/
fun ChangeCoordinate(lat: Double, long: Double) {
coordinate = Coordinates(lat, long)
}
// /**
// * Set prayer time adjustments in minutes.
// * @param fajrMinute Adjustment for Fajr prayer time in minutes.
// * @param dhuhrMinute Adjustment for Dhuhr prayer time in minutes.
// * @param asrMinute Adjustment for Asr prayer time in minutes.
// * @param maghribMinute Adjustment for Maghrib prayer time in minutes.
// * @param ishaMinute Adjustment for Isha prayer time in minutes.
// */
// fun SetPrayerAdjustment(fajrMinute: Int = 0, dhuhrMinute: Int = 0, asrMinute: Int = 0,maghribMinute: Int = 0, ishaMinute: Int = 0) {
// params.adjustments.fajr = fajrMinute
// params.adjustments.dhuhr = dhuhrMinute
// params.adjustments.asr = asrMinute
// params.adjustments.maghrib = maghribMinute
// params.adjustments.isha = ishaMinute
// }
// /**
// * Change the coordinates used for Adzan calculations.
// * @param lat The new latitude.
// * @param long The new longitude.
// */
// fun ChangeCoordinate(lat: Double, long: Double) {
// coordinate = Coordinates(lat, long)
// }
fun ChangeLatitude(lat: Double) {
coordinate = Coordinates(lat, coordinate.longitude)
@@ -92,19 +185,19 @@ class Table_Adzan(val latitude: Double = -6.1751, val longitude: Double = 106.82
coordinate = Coordinates(coordinate.latitude, long)
}
/**
* Get prayer times for a specific date string in the format "dd/MM/yyyy".
* @param date_string The date string for which to get prayer times.
* @return An AdzanPrayerTime object containing the prayer times, or null if the date string is invalid.
*/
fun GetPrayerTimes(date_string: String) : AdzanPrayerTime?{
try{
val date = dateformatter.parse(date_string)
return GetPrayerTimes(date)
} catch (e: Exception){
return null
}
}
// /**
// * Get prayer times for a specific date string in the format "dd/MM/yyyy".
// * @param date_string The date string for which to get prayer times.
// * @return An AdzanPrayerTime object containing the prayer times, or null if the date string is invalid.
// */
// fun GetPrayerTimes(date_string: String) : AdzanPrayerTime?{
// try{
// val date = dateformatter.parse(date_string)
// return GetPrayerTimes(date)
// } catch (_: Exception){
// return null
// }
// }
/**
* Get prayer times for a specific date.
@@ -125,31 +218,38 @@ class Table_Adzan(val latitude: Double = -6.1751, val longitude: Double = 106.82
/**
* Get prayer times for the current date.
* this will update fajar_time, dzuhur_time, ashar_time, maghrib_time, isya_time properties
* @return An AdzanPrayerTime object containing the prayer times for today.
*/
fun GetTodayPrayerTimes() : AdzanPrayerTime{
return GetPrayerTimes(Date())
val result = GetPrayerTimes(Date())
fajar_time = result.fajr
dzuhur_time = result.dhuhr
ashar_time = result.asr
maghrib_time = result.maghrib
isya_time = result.isha
return result
}
/**
* Get prayer times for all days in a specific month and year.
* @param month The month (1-12) for which to get prayer times.
* @param year The year for which to get prayer times.
* @return A list of AdzanPrayerTime objects for each day in the specified month and year.
*/
fun GetMonthlyPrayerTimes(month: Int, year: Int) : List<AdzanPrayerTime>{
val prayerTimesList = mutableListOf<AdzanPrayerTime>()
val calendar = java.util.Calendar.getInstance()
calendar.set(year, month - 1, 1) // Month is 0-based in Calendar
val daysInMonth = calendar.getActualMaximum(java.util.Calendar.DAY_OF_MONTH)
for (day in 1..daysInMonth) {
calendar.set(year, month - 1, day)
val date = calendar.time
val prayerTimes = GetPrayerTimes(date)
prayerTimesList.add(prayerTimes)
}
return prayerTimesList
}
// /**
// * Get prayer times for all days in a specific month and year.
// * @param month The month (1-12) for which to get prayer times.
// * @param year The year for which to get prayer times.
// * @return A list of AdzanPrayerTime objects for each day in the specified month and year.
// */
// fun GetMonthlyPrayerTimes(month: Int, year: Int) : List<AdzanPrayerTime>{
// val prayerTimesList = mutableListOf<AdzanPrayerTime>()
// val calendar = java.util.Calendar.getInstance()
// calendar.set(year, month - 1, 1) // Month is 0-based in Calendar
// val daysInMonth = calendar.getActualMaximum(java.util.Calendar.DAY_OF_MONTH)
//
// for (day in 1..daysInMonth) {
// calendar.set(year, month - 1, day)
// val date = calendar.time
// val prayerTimes = GetPrayerTimes(date)
// prayerTimesList.add(prayerTimes)
// }
//
// return prayerTimesList
// }
}

View File

@@ -1,7 +1,6 @@
package database.table
import StreamerOutputs
import broadcastDB
import codes.Somecodes.Companion.ValidIPV4
import codes.Somecodes.Companion.ValidString
import database.data.BroadcastZones
@@ -223,8 +222,8 @@ class Table_BroadcastZones(connection: Connection) : dbFunctions<BroadcastZones>
}
/**
* Check if all broadcast zones in a comma-separated string are valid
* Valid means the broadcast zone name exists in the BroadcastZones table, its SoundChannel exists in the SoundChannel table, and its IP is valid
* Check if all broadcast zones in a comma-separated string are valid,
* means the broadcast zone name exists in the BroadcastZones table, its SoundChannel exists in the SoundChannel table, and its IP is valid
* @param zones Comma-separated string of broadcast zones
* @param checkOnline Whether to check if the sound channel is really online, recorded in StreamerOutputs map
* @return true if all broadcast zones are valid, false otherwise

View File

@@ -258,4 +258,25 @@ class Table_Messagebank(connection: Connection) : dbFunctions<Messagebank>("mess
}
return false
}
/**
* Find a messagebank entry based on messagedetail and language
* @param messagedetail the messagedetail in format "message_name [ann_id]"
* @param language the language to find
* @return the messagebank entry if found, null otherwise
*/
fun Find_Messagebank(messagedetail: String, language: String) : Messagebank?{
return try{
val match = messageDetailRegex.find(messagedetail)
if (match != null){
val msg = match.groupValues[1].trim()
val annid = match.groupValues[2].toUIntOrNull() ?: return null // kalau bukan number, return null
List.firstOrNull{ it.ANN_ID == annid && it.Description == msg && it.Language.equals(language, ignoreCase = true) }
} else {
null
}
} catch (_: Exception){
null
}
}
}

View File

@@ -55,12 +55,13 @@ import io.javalin.websocket.WsCloseStatus
import logDB
import messageDB
import org.tinylog.Logger
import queuepagingDB
import queuetableDB
import soundchannelDB
import version
import java.io.File
import java.nio.ByteBuffer
import java.nio.file.Path
import java.util.TimeZone
import java.util.UUID
@@ -221,7 +222,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(db.queuepagingDB.List)
objectmapper.writeValueAsString(queuepagingDB.List)
)
}
@@ -229,7 +230,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(db.queuetableDB.List)
objectmapper.writeValueAsString(queuetableDB.List)
)
}
@@ -362,7 +363,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(db.queuepagingDB.List)
objectmapper.writeValueAsString(queuepagingDB.List)
)
}
@@ -370,7 +371,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
SendReply(
wsMessageContext,
cmd.command,
objectmapper.writeValueAsString(db.queuetableDB.List)
objectmapper.writeValueAsString(queuetableDB.List)
)
}
@@ -2180,8 +2181,8 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
path("QueuePaging") {
get("List") { ctx ->
db.queuepagingDB.Get({
ctx.json(db.queuepagingDB.List)
queuepagingDB.Get({
ctx.json(queuepagingDB.List)
}, { msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
})
@@ -2189,8 +2190,8 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
}
delete("List") {
// truncate queue paging table
if (db.queuepagingDB.Clear()) {
db.queuepagingDB.Get()
if (queuepagingDB.Clear()) {
queuepagingDB.Get()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else {
it.status(500)
@@ -2204,8 +2205,8 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.queuepagingDB.DeleteByIndex(index.toInt())) {
db.queuepagingDB.Resort()
if (queuepagingDB.DeleteByIndex(index.toInt())) {
queuepagingDB.Resort()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
logDB.Add("AAS", "Deleted queue paging with index $index")
} else {
@@ -2218,8 +2219,8 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
}
path("QueueTable") {
get("List") { ctx ->
db.queuetableDB.Get({
ctx.json(db.queuetableDB.List)
queuetableDB.Get({
ctx.json(queuetableDB.List)
}, { msgFail ->
ctx.status(500).result(objectmapper.writeValueAsString(resultMessage(msgFail)))
})
@@ -2227,8 +2228,8 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
}
delete("List") {
// truncate queue table
if (db.queuetableDB.Clear()) {
db.queuetableDB.Get()
if (queuetableDB.Clear()) {
queuetableDB.Get()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else {
it.status(500)
@@ -2242,8 +2243,8 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.queuetableDB.DeleteByIndex(index.toInt())) {
db.queuetableDB.Resort()
if (queuetableDB.DeleteByIndex(index.toInt())) {
queuetableDB.Resort()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
logDB.Add("AAS", "Deleted queue sound with index $index")
@@ -2470,28 +2471,30 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
}
}
path("Settings") {
get("TimezoneList"){
it.json(Somecodes.Get_TimeZones())
}
path("AdzanSetting"){
get{
val todayadzan = adzanTable.GetTodayPrayerTimes()
val value = AdzanSetting(
latitude = _config.Get(configKeys.LATITUDE.key).toDoubleOrNull() ?: 0.0,
longitude = _config.Get(configKeys.LONGITUDE.key).toDoubleOrNull() ?: 0.0,
timezone = _config.Get(configKeys.TIMEZONE.key),
fajar_sound = _config.Get(configKeys.ADZAN_FAJR_SOUND.key),
fajar_enable = _config.Get(configKeys.ADZAN_FAJR_ENABLED.key).toBoolean(),
fajar_time = todayadzan.fajr,
fajar_time = adzanTable.fajar_time,
dzuhur_sound = _config.Get(configKeys.ADZAN_DHUHR_SOUND.key),
dzuhur_enable = _config.Get(configKeys.ADZAN_DHUHR_ENABLED.key).toBoolean(),
dzuhur_time = todayadzan.dhuhr,
dzuhur_time = adzanTable.dzuhur_time,
ashar_sound = _config.Get(configKeys.ADZAN_ASR_SOUND.key),
ashar_enable = _config.Get(configKeys.ADZAN_FAJR_ENABLED.key).toBoolean(),
ashar_time = todayadzan.asr,
ashar_time = adzanTable.ashar_time,
maghrib_sound = _config.Get(configKeys.ADZAN_MAGHRIB_SOUND.key),
maghrib_enable = _config.Get(configKeys.ADZAN_MAGHRIB_ENABLED.key).toBoolean(),
maghrib_time = todayadzan.maghrib,
maghrib_time = adzanTable.maghrib_time,
isya_sound = _config.Get(configKeys.ADZAN_ISHA_SOUND.key),
isya_enable = _config.Get(configKeys.ADZAN_ISHA_ENABLED.key).toBoolean(),
isya_time = todayadzan.isha
isya_time = adzanTable.isya_time
)
it.json(value)
}
@@ -2499,6 +2502,7 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
val json: JsonNode = objectmapper.readTree(it.body())
try{
val newsetting = AdzanSetting.FromJsonNode(json)
var need_recalculate_adzan_today = false
_config.CompareWithAdzanSetting(newsetting).let { changes ->
if (changes.isNotEmpty()){
// something changes
@@ -2506,19 +2510,28 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
_config.Set(change.key, change.newValue)
Logger.info{"AdzanSetting change: ${change.key} from ${change.oldValue} to ${change.newValue}"}
when(change.key){
configKeys.LATITUDE.key -> adzanTable.ChangeLatitude(change.newValue.toDouble())
configKeys.LONGITUDE.key -> adzanTable.ChangeLongitude(change.newValue.toDouble())
configKeys.TIMEZONE.key -> adzanTable.ChangeTimeZone(change.newValue)
configKeys.LATITUDE.key -> {
adzanTable.ChangeLatitude(change.newValue.toDouble())
need_recalculate_adzan_today = true
}
configKeys.LONGITUDE.key -> {
adzanTable.ChangeLongitude(change.newValue.toDouble())
need_recalculate_adzan_today = true
}
configKeys.TIMEZONE.key -> {
adzanTable.ChangeTimeZone(change.newValue)
need_recalculate_adzan_today = true
}
configKeys.ADZAN_FAJR_ENABLED.key -> adzanTable.fajar_enable = change.newValue.toBoolean()
configKeys.ADZAN_DHUHR_ENABLED.key -> adzanTable.dzuhur_enable = change.newValue.toBoolean()
configKeys.ADZAN_ASR_ENABLED.key -> adzanTable.ashar_enable = change.newValue.toBoolean()
configKeys.ADZAN_MAGHRIB_ENABLED.key -> adzanTable.maghrib_enable = change.newValue.toBoolean()
configKeys.ADZAN_ISHA_ENABLED.key -> adzanTable.isya_enable = change.newValue.toBoolean()
configKeys.ADZAN_FAJR_SOUND.key -> adzanTable.fajar_sound = change.newValue
configKeys.ADZAN_DHUHR_SOUND.key -> adzanTable.dzuhur_sound = change.newValue
configKeys.ADZAN_ASR_SOUND.key -> adzanTable.ashar_sound = change.newValue
configKeys.ADZAN_MAGHRIB_SOUND.key -> adzanTable.maghrib_sound = change.newValue
configKeys.ADZAN_ISHA_SOUND.key -> adzanTable.isya_sound = change.newValue
configKeys.ADZAN_FAJR_SOUND.key -> adzanTable.fajar_message = change.newValue
configKeys.ADZAN_DHUHR_SOUND.key -> adzanTable.dzuhur_message = change.newValue
configKeys.ADZAN_ASR_SOUND.key -> adzanTable.ashar_message = change.newValue
configKeys.ADZAN_MAGHRIB_SOUND.key -> adzanTable.maghrib_message = change.newValue
configKeys.ADZAN_ISHA_SOUND.key -> adzanTable.isya_message = change.newValue
else -> {
// nothing to do
@@ -2531,9 +2544,28 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
Logger.info { "No changes detected in AdzanSetting"}
}
}
if (need_recalculate_adzan_today) {
adzanTable.GetTodayPrayerTimes()
}
if (newsetting.fajar_time != adzanTable.fajar_time){
adzanTable.fajar_time = newsetting.fajar_time
}
if (newsetting.dzuhur_time != adzanTable.dzuhur_time){
adzanTable.dzuhur_time = newsetting.dzuhur_time
}
if (newsetting.ashar_time != adzanTable.ashar_time){
adzanTable.ashar_time = newsetting.ashar_time
}
if (newsetting.maghrib_time != adzanTable.maghrib_time){
adzanTable.maghrib_time = newsetting.maghrib_time
}
if (newsetting.isya_time != adzanTable.isya_time){
adzanTable.isya_time = newsetting.isya_time
}
Logger.info{"AdzanSetting updated successfully"}
Logger.info{"Today's Prayer Times: Fajar=${adzanTable.fajar_time}, Dzuhur=${adzanTable.dzuhur_time}, Ashar=${adzanTable.ashar_time}, Maghrib=${adzanTable.maghrib_time}, Isya=${adzanTable.isya_time}"}
Logger.info{"Fajar Enabled=${adzanTable.fajar_enable}, Dzuhur Enabled=${adzanTable.dzuhur_enable}, Ashar Enabled=${adzanTable.ashar_enable}, Maghrib Enabled=${adzanTable.maghrib_enable}, Isya Enabled=${adzanTable.isya_enable}"}
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} catch (e : Exception){
it.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Incomplete AdzanSetting data: ${e.message}")))
@@ -2804,18 +2836,15 @@ class WebApp(val listenPort: Int, var userlist: List<Pair<String, String>>, val
if (tags.isNotEmpty()) {
if (broadcastzones.isNotEmpty()) {
val qt = QueueTable(
0u,
LocalDateTime.now().format(datetimeformat1),
"SEMIAUTOWEB",
"SOUNDBANK",
description,
tags,
broadcastzones,
1u,
languages
Source ="SEMIAUTOWEB",
Type="SOUNDBANK",
Message=description,
SB_TAGS =tags,
BroadcastZones = broadcastzones,
Language=languages
)
if (db.queuetableDB.Add(qt)) {
db.queuetableDB.Resort()
if (queuetableDB.Add(qt)) {
queuetableDB.Resort()
Logger.info { "SemiAutoWeb added to queue table: $qt" }
ctx.result(objectmapper.writeValueAsString(resultMessage("OK")))
db.logSemiAuto.Add(