diff --git a/.gitignore b/.gitignore index d0baf01..44ffb8e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ out/ build/ /data/ +/config/ /logs/ /run /colors diff --git a/settings.gradle.kts b/settings.gradle.kts index 70d23c2..915f10f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,7 @@ pluginManagement { } plugins { - id("com.gradle.enterprise") version "3.15.1" + id("com.gradle.enterprise") version "3.16.1" id("de.fayard.refreshVersions") version "0.60.3" } diff --git a/src/main/kotlin/moe/nikky/BotInfoExtension.kt b/src/main/kotlin/moe/nikky/BotInfoExtension.kt index ff2050d..e8b6984 100644 --- a/src/main/kotlin/moe/nikky/BotInfoExtension.kt +++ b/src/main/kotlin/moe/nikky/BotInfoExtension.kt @@ -9,7 +9,7 @@ import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.ephemeralSlashCommand import dev.kord.common.entity.Permission import dev.kord.common.entity.Permissions -import dev.kord.rest.builder.message.create.embed +import dev.kord.rest.builder.message.embed import io.klogging.Klogging import io.ktor.http.* import kotlinx.coroutines.flow.count diff --git a/src/main/kotlin/moe/nikky/LocalTimeExtension.kt b/src/main/kotlin/moe/nikky/LocalTimeExtension.kt index 66eb631..5b34c6a 100644 --- a/src/main/kotlin/moe/nikky/LocalTimeExtension.kt +++ b/src/main/kotlin/moe/nikky/LocalTimeExtension.kt @@ -1,6 +1,7 @@ package moe.nikky import com.kotlindiscord.kord.extensions.commands.Arguments +import com.kotlindiscord.kord.extensions.commands.application.slash.ephemeralSubCommand import com.kotlindiscord.kord.extensions.commands.converters.impl.string import com.kotlindiscord.kord.extensions.commands.converters.impl.user import com.kotlindiscord.kord.extensions.extensions.Extension @@ -12,18 +13,19 @@ import com.kotlindiscord.kord.extensions.storage.StorageUnit import com.kotlindiscord.kord.extensions.utils.suggestStringMap import dev.kord.common.entity.Snowflake import dev.kord.core.behavior.GuildBehavior -import dev.kord.core.entity.Guild import dev.kord.core.entity.User -import dev.kord.rest.builder.message.create.embed +import dev.kord.rest.builder.message.embed import io.klogging.Klogging +import io.ktor.client.request.forms.* +import io.ktor.utils.io.* import kotlinx.datetime.Clock import kotlinx.datetime.IllegalTimeZoneException import kotlinx.datetime.Instant import kotlinx.datetime.TimeZone import kotlinx.datetime.offsetAt -import kotlinx.datetime.toInstant import kotlinx.datetime.toLocalDateTime import kotlinx.serialization.Serializable +import kotlin.time.Duration import kotlin.time.Duration.Companion.ZERO import kotlin.time.Duration.Companion.seconds @@ -48,9 +50,9 @@ class LocalTimeExtension : Extension(), Klogging { "UTC", "GMT", "Europe/London", "CET", "Europe/Berlin", "Europe/Paris", "NZ", "Japan", "Asia/Tokyo", - "Asia/Manila", "Asia/Kolkata", "Asia/Jakarta", - "US/Eastern", "US/Central", "America/New_York", - "US/Pacific", "America/Sao_Paulo", "America/Chicago", + "US/Alaska", "US/Pacific", "US/Mountain", + "US/Central", "US/Eastern", "Canada/Eastern", + "America/New_York", "America/Sao_Paulo", "America/Chicago", "America/Los_Angeles", "Europe/Moscow", "Singapore", ) } @@ -61,45 +63,80 @@ class LocalTimeExtension : Extension(), Klogging { name = "timezone" description = "list or set timezones" - action { - withLogContext(event, guild) { guild -> - logger.infoF { "received timezone id: ${arguments.timezoneId}" } - val timezone = try { - TimeZone.of(arguments.timezoneId) - } catch (e: IllegalTimeZoneException) { - respond { - content = "Possibly you meant one of the following timezones?" - embed { - SUGGEST_TIMEZONES.mapNotNull { zoneId -> - try { - TimeZone.of(zoneId) - } catch (e: IllegalTimeZoneException) { - logger.errorF { "incorrect timezone id: '$zoneId'" } - null - } - }.forEach { timezone -> - field { - val formattedTime = formatTime(Clock.System.now(), timezone) - name = timezone.id - value = "\uD83D\uDD57 `$formattedTime`" - inline = true + ephemeralSubCommand(::TimezoneArgs) { + name = "set" + description = "update your timezone" + + action { + withLogContext(event, guild) { guild -> + logger.infoF { "received timezone id: ${arguments.timezoneId}" } + val timezone = try { + TimeZone.of(arguments.timezoneId) + } catch (e: IllegalTimeZoneException) { + respond { + content = + """Possibly you meant one of the following timezones? + |for a full list of availabe zone ids run + |``` + |/timezone list + |``` + |""".trimMargin() + embed { + SUGGEST_TIMEZONES.mapNotNull { zoneId -> + try { + TimeZone.of(zoneId) + } catch (e: IllegalTimeZoneException) { + logger.errorF { "incorrect timezone id: '$zoneId'" } + null + } + }.forEach { timezone -> + field { + val formattedTime = formatTime(Clock.System.now(), timezone) + name = timezone.id + value = "\uD83D\uDD57 `$formattedTime`" + inline = true + } } } } + return@withLogContext + } + + val configStorage = guild.config(event.interaction.user.id) + configStorage.save( + TimezoneConfig(timezoneId = timezone.id) + ) + + respond { + val formattedTime = formatTime(Clock.System.now(), timezone) + + content = + "Timezone has been set to **${timezone.id}**. Your current time should be `$formattedTime`" } - return@withLogContext } + } + } - val configStorage = guild.config(event.interaction.user.id) - configStorage.save( - TimezoneConfig(timezoneId = timezone.id) - ) + ephemeralSubCommand() { + name = "list" + description = "sends a list of valid timezones" - respond { - val formattedTime = formatTime(Clock.System.now(), timezone) + action { + withLogContext(event, guild) { guild -> + val timezones = TimeZone.sortedList().map { (tz, offset) -> + "${offset.toString().padEnd(10, ' ')} ${tz.id}" + } + + respond { + content = "a list of valid timezone ids is in the attachment" - content = - "Timezone has been set to **${timezone.id}**. Your current time should be `$formattedTime`" + addFile( + "timezones.txt", + ChannelProvider { + ByteReadChannel(timezones.joinToString("\n")) + } + ) + } } } } @@ -150,7 +187,7 @@ class LocalTimeExtension : Extension(), Klogging { targetUser: User, selfUser: User, ): String { - val targetConfig = guild.config(targetUser.id).get() + val targetConfig = guild.config(targetUser.id).get() val selfConfig = guild.config(selfUser.id).get() if (targetConfig == null) { @@ -208,6 +245,7 @@ class LocalTimeExtension : Extension(), Klogging { } } } + inner class TimezoneTargetArgs : Arguments() { val user by user { name = "user" @@ -223,3 +261,24 @@ data class TimezoneConfig( ) : Data { val timezone: TimeZone by lazy { TimeZone.of(timezoneId) } } + +fun TimeZone.Companion.sortedList(): List> { + val now = Clock.System.now() + return TimeZone.availableZoneIds + .map { zoneId -> + TimeZone.of(zoneId) + } + .sortedBy { tz -> + tz.offsetAt(now).totalSeconds + }.map { tz -> + val offset = tz.offsetAt(now) + val hoursOffset = -offset.totalSeconds.seconds + tz to hoursOffset + } +} + +fun main() { + TimeZone.sortedList().forEach { (tz, offset) -> + println("${offset.toString().padEnd(10, ' ')} ${tz.id}") + } +} diff --git a/versions.properties b/versions.properties index b554cfa..5fd5643 100644 --- a/versions.properties +++ b/versions.properties @@ -9,22 +9,20 @@ plugin.com.github.johnrengelman.shadow=8.1.1 -plugin.com.google.devtools.ksp=1.9.10-1.0.13 -## # available=1.9.20-Beta-1.0.13 -## # available=1.9.20-Beta2-1.0.13 -## # available=1.9.20-RC-1.0.13 -## # available=1.9.20-RC2-1.0.13 -## # available=1.9.20-1.0.13 +plugin.com.google.devtools.ksp=1.9.22-1.0.16 +## # available=2.0.0-Beta1-1.0.14 +## # available=2.0.0-Beta1-1.0.15 +## # available=2.0.0-Beta2-1.0.16 version.br.com.colman..dice-helper=1.0.0 version.io.github.xn32..json5k=0.3.0 ## # available=0.4.0-SNAPSHOT -version.io.klogging..klogging-jvm=0.5.6 +version.io.klogging..klogging-jvm=0.5.8 ## # available=0.6.0-SNAPSHOT -version.io.klogging..slf4j-klogging=0.5.6 +version.io.klogging..slf4j-klogging=0.5.8 ## # available=0.6.0-SNAPSHOT version.junit.jupiter=5.10.0 @@ -35,14 +33,13 @@ version.kord.extensions=1.6.0-SNAPSHOT version.kord.x.emoji=0.5.0 -version.kotlin=1.9.10 -## # available=1.9.20-Beta -## # available=1.9.20-Beta2 -## # available=1.9.20-RC -## # available=1.9.20-RC2 -## # available=1.9.20 +version.kotlin=1.9.22 +## # available=2.0.0-Beta1 +## # available=2.0.0-Beta2 version.kotlinx.coroutines=1.7.3 +## # available=1.8.0-RC +## # available=1.8.0-RC2 version.kotlinx.datetime=0.4.1 @@ -50,4 +47,6 @@ version.kotlinx.serialization=1.6.0 version.ktor=2.3.5 -version.org.slf4j..slf4j-api=2.0.9 +version.org.slf4j..slf4j-api=2.0.11 +## # available=2.1.0-alpha0 +## # available=2.1.0-alpha1