diff --git a/.forgejo/workflows/action.yml b/.forgejo/workflows/action.yml new file mode 100644 index 0000000..8418c1c --- /dev/null +++ b/.forgejo/workflows/action.yml @@ -0,0 +1,25 @@ +name: Build Gradle project + +on: + push: + +jobs: + build-gradle-project: + runs-on: ubuntu-latest + steps: + - name: apt update + run: apt update + - name: apt upgrade + run: apt upgrade -y + - name: install prerequisits + run: apt install openjdk-17-jdk ca-certificates-java ssl-cert openssl ca-certificates -y + - name: Checkout project sources + uses: actions/checkout@v3 + - name: Setup Gradle + uses: gradle/gradle-build-action@v2 + - name: Run build with Gradle Wrapper + run: ./gradlew shadowJar + - uses: actions/upload-artifact@v3 + with: + name: lilJudd.jar + path: build/libs/ diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml deleted file mode 100644 index d7453ff..0000000 --- a/.forgejo/workflows/build.yml +++ /dev/null @@ -1,15 +0,0 @@ -on: [ push ] -jobs: - build_and_publish: - runs-on: gradle - steps: - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - name: Clean Caches - run: | - rm -f .gradle/caches/modules-2/modules-2.lock - rm -fr .gradle/caches/*/plugin-resolution/ - - name: Run shadowJar - run: ./gradlew shadowJar - - name: Run publish - run: ./gradlew publish diff --git a/.gitignore b/.gitignore index ce11a8e..f970cd0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ run/ +/data/ .gradle build/ diff --git a/README.md b/README.md index 14b1834..6d87924 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,9 @@ "Oh boy, here we go again" ~ me -A Discord Bot for Splatoon Teams +A Discord Bot for Splatoon Teams. -[![Latest Release](https://gitlab.com/moonleay/liljudd/-/badges/release.svg)](https://gitlab.com/moonleay/liljudd/-/releases) -[![pipeline status](https://gitlab.com/moonleay/liljudd/badges/master/pipeline.svg)](https://gitlab.com/moonleay/liljudd/-/commits/master) -[![License](https://img.shields.io/badge/license-GPL--3.0-brightgreen)](https://gitlab.com/moonleay/liljudd/-/blob/master/LICENSE) +More information can be found on the [Homepage](https://liljudd.ink). ## Contributors @@ -14,55 +12,49 @@ A Discord Bot for Splatoon Teams ## Known issues -##### If you encounter any bugs, message me on Discord (@moonleay) or send me a mail (issues@moonleay.net). +##### If you encounter any bugs, message me on Discord (@moonleay) or send me a mail (issues@moonleay.net). You can also open a ticket [on the support server](https://discord.gg/HTZRktfH4A). ## Commands & Features - Commands - version -- Show the versions of the bot and the most important dependencies - feature -- Manage bot features + - match -- Create a new match + - updateroles -- Update the roles of all users + - sendplanner -- Send the planner message - Features - Time Planner -- Make the bot send messages and reactions into a selected channel in order to make planning easier - Availability Manager -- Make the bot assign users roles every day, so it is possible to notify available people + - Match Planner -- Make a match, for which players can sign up and the bot will assign teams and roles to them ## (Maybe) upcoming features -- Match Planner (Send Notifications some time before a match starts) -- Game Tracker (Save the results of the last matches) -- Replay Saver (Maybe; will save the replay code to a database) -- Rndm map command -- Maybe a DSB / DSL API - -## TODO - -- Rewrite the Database connection system (from transactions all over the place to a single package with transactions) +##### See the [todo list](https://todo.moonleay.net/share/OmisuzgPDdsrCAXKjGrTfYzWwqNDNclOMGJWeMsi/auth?view=kanban) for more information. ## How to self-host (using the Docker container) -1. Pull the container +1. Pull the container from [Docker Hub](https://hub.docker.com/repository/docker/limiteddev/liljudd/general) 2. Map /data/ to a folder on disk 3. Run the Bot once -4. Follow step 4 - 7 of "How to self-host (using the JAR)" +4. follow step 4 and 5 from the JAR section +5. Run the Bot again +6. Profit. ## How to self-host (using the JAR) -1. Download the latest release from the Package Registry ("Packages and registries" > "Package Registry") - 1. It should be called something like this: "lilJudd-X.X.X-xxxxxxxx-prod.jar" (replace "X.X.X" with the latest - version and xxxxxxxx" with the commit its based on.) - 2. If you want to run an early version, which may be (very) unsable, you can run a development version. Just use an - entry ending in "-dev.jar" +1. Download the latest release from the Releases page. 2. Place it anywhere you want. 3. Run the following command: - > java -jar lilJudd-X.X.X-xxxxxxxx-prod.jar + > java -jar lilJudd.jar 4. The bot should start and create a config file named "credentials.nils" in a folder called "data" 5. Open it and put in your credentials. 1. token: your Discord bot token 2. dbDomain: the domain and port of your postgresql database (e.g.: 192.168.178.1:5432) - 3. dbName: the name of your database + 3. dbName: the name of the database 4. dbUser: the username of the database - 5. dbPassword: the password to your user + 5. dbPassword: the password to the db user 6. Rerun the command - > java -jar lilJudd-X.X.X-xxxxxxxx-prod.jar + > java -jar lilJudd.jar 7. The bot should now be up and running. ## How to set up workspace diff --git a/build.gradle.kts b/build.gradle.kts index f62ca80..48416b1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,9 +21,9 @@ import org.jetbrains.gradle.ext.TaskTriggersConfig import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.8.20" - id("com.github.johnrengelman.shadow") version "7.1.2" - id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.6" + kotlin("jvm") version "1.9.10" + id("com.github.johnrengelman.shadow") version "8.1.1" + id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7" `maven-publish` } @@ -32,14 +32,14 @@ val ownerID = 372703841151614976L group = "net.moonleay.liljudd" version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" } ?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" } - ?: "2.4.2" + ?: "2.6.5" -val kordver = "1.5.6" -val coroutinesver = "1.1.0" -val ktor_version = "2.3.0" -val exposedver = "0.40.1" -val postgresver = "42.3.8" -val krontabver = "2.1.2" +val kordver = "1.5.9-SNAPSHOT" +val coroutinesver = "1.7.3" +val ktorver = "2.3.5" +val exposedver = "0.43.0" +val postgresver = "42.6.0" +val krontabver = "2.2.1" val mavenArtifact = "lilJudd" project.base.archivesName.set(mavenArtifact) @@ -72,6 +72,14 @@ repositories { } } } + maven { + name = "sonatype" + url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots") + } + maven { + name = "sonatype 2" + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } } val shadow by configurations.getting @@ -81,6 +89,8 @@ implementation.extendsFrom(shadow) dependencies { //Discord shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordver") + + //Coroutines shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver") //Logging @@ -93,22 +103,22 @@ dependencies { shadow("org.jetbrains.exposed:exposed-jdbc:$exposedver") shadow("org.postgresql:postgresql:$postgresver") - //Korntab + //Krontab shadow("dev.inmo:krontab:$krontabver") - "shadow"("io.ktor:ktor-client-core-jvm:2.3.1") - "shadow"("io.ktor:ktor-client-cio-jvm:2.3.1") + shadow("io.ktor:ktor-client-core-jvm:2.3.5") + shadow("io.ktor:ktor-client-cio-jvm:2.3.5") } val targetJavaVersion = 17 val templateSrc = project.rootDir.resolve("src/main/templates") -val templateDest = project.buildDir.resolve("generated/templates") +val templateDest = project.projectDir.resolve("build/generated/templates") val templateProps = mapOf( "version" to project.version as String, "ownerID" to ownerID, "kordversion" to kordver, "coroutinesversion" to coroutinesver, - "ktorversion" to ktor_version, + "ktorversion" to ktorver, "exposedversion" to exposedver, "postgresversion" to postgresver, "krontabversion" to krontabver diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e583..41d9927 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 21995b6..14cf480 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -18,6 +18,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/kotlin/net/moonleay/lilJudd/Bot.kt b/src/main/kotlin/net/moonleay/lilJudd/Bot.kt index be764de..05f7ba8 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/Bot.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/Bot.kt @@ -19,7 +19,6 @@ package net.moonleay.lilJudd import com.kotlindiscord.kord.extensions.ExtensibleBot -import dev.kord.common.Color import dev.kord.common.entity.PresenceStatus import dev.kord.core.behavior.interaction.response.respond import dev.kord.core.event.gateway.ReadyEvent @@ -31,19 +30,17 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch -import net.moonleay.botendo.build.BuildConstants import net.moonleay.lilJudd.buttons.component.EditButtonManager import net.moonleay.lilJudd.data.CredentialManager -import net.moonleay.lilJudd.data.DB -import net.moonleay.lilJudd.extensions.FeatureManageExtension -import net.moonleay.lilJudd.extensions.MatchExtension -import net.moonleay.lilJudd.extensions.SendPlannerExtension -import net.moonleay.lilJudd.extensions.VersionExtension +import net.moonleay.lilJudd.data.database.DB +import net.moonleay.lilJudd.extensions.* import net.moonleay.lilJudd.features.AvailabilityManager import net.moonleay.lilJudd.features.MatchManager import net.moonleay.lilJudd.features.TimeManager +import net.moonleay.lilJudd.util.EmbedColor import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.MessageUtil +import net.moonleay.liljudd.build.BuildConstants import kotlin.system.exitProcess object Bot { @@ -79,6 +76,9 @@ object Bot { CredentialManager.dbPassword ) + // Make sure the database is up-to-date + DB.register() + // Register all the jobs jobs.addAll( listOf( @@ -99,12 +99,11 @@ object Bot { } extensions { - add(::VersionExtension) + add(::InfoExtension) add(::FeatureManageExtension) add(::SendPlannerExtension) add(::MatchExtension) - //add(::UpdateRolesExtension) // This command is only for debugging purposes - //add(::TestExtension) // See comment in TestExtension.kt + add(::UpdateRolesExtension) } this.presence { @@ -121,7 +120,6 @@ object Bot { sharding { recommended -> Shards(recommended) } */ - // Same goes for a Database table rewrite } // Register button presses @@ -142,13 +140,13 @@ object Bot { } if (inter.componentId.startsWith("public.message.")) { val response = inter.deferPublicResponse() - val g = this.interaction.getOriginalInteractionResponse().getGuild() response.respond { this.embeds = mutableListOf( MessageUtil.getEmbed( - Color(0xE0311A), - "Error", - "Could not find button with id \"${inter.componentId}\".\nPlease report this.", + EmbedColor.ERROR, + "404: Not Found", + "Could not find button with id \"${inter.componentId}\"." + + "\nPlease report this.", u.asUser().username + "#" + u.asUser().discriminator ) ) @@ -159,8 +157,24 @@ object Bot { bot.kordRef.on { AvailabilityManager.runThread() // Update Availabilities MatchManager.update() // Update Matches + // Make the bot update the status every 6 seconds + // JobManager.addJob(StatusUpdater) } + // Update the Splatoon 3 api data and make sure it stays up-to-date + // Splatoon3ApiCache.updateData(ApiDataType.SCHEDULES, ApiRequestType.AUTOMATIC_CACHE_CREATION_AT_STARTUP) + // JobManager.addJob(Splatoon3ApiScheduleUpdateScheduler) + /* + Other caches will be added when implemented + its not used yet in order to reduce load on the api, + which i am using. + */ + // Had to disable bc of an error. + // Will fix when I have time + + + //JobManager.addJob(Splatoon3ApiFestivalAndCoopUpdateScheduler) + //JobManager.addJob(Splatoon3ApiSplatnetGearUpdateScheduler) //Start the bot bot.start() diff --git a/src/main/kotlin/net/moonleay/lilJudd/Main.kt b/src/main/kotlin/net/moonleay/lilJudd/Main.kt index 9d00d29..36be8b3 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/Main.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/Main.kt @@ -17,7 +17,8 @@ */ package net.moonleay.lilJudd -import net.moonleay.botendo.build.BuildConstants +import net.moonleay.liljudd.build.BuildConstants + suspend fun main() { println( diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/component/EditButtonManager.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/component/EditButtonManager.kt index 070f25a..f0df57f 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/buttons/component/EditButtonManager.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/component/EditButtonManager.kt @@ -18,8 +18,9 @@ package net.moonleay.lilJudd.buttons.component +import net.moonleay.lilJudd.buttons.matchplanner.AcceptEditButton import net.moonleay.lilJudd.buttons.matchplanner.CancelEditButton -import net.moonleay.lilJudd.buttons.matchplanner.SignMeUpEditButton +import net.moonleay.lilJudd.buttons.matchplanner.DeclineEditButton import net.moonleay.lilJudd.buttons.timeplanner.IsAvailableEditButton import net.moonleay.lilJudd.buttons.timeplanner.MaybeAvailableEditButton import net.moonleay.lilJudd.buttons.timeplanner.NotAvailableEditButton @@ -29,7 +30,8 @@ object EditButtonManager { IsAvailableEditButton(), MaybeAvailableEditButton(), NotAvailableEditButton(), - SignMeUpEditButton(), - CancelEditButton() + AcceptEditButton(), + CancelEditButton(), + DeclineEditButton(), ) } diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/component/IEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/component/IEditButton.kt index 84e8a5b..0fbe64e 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/buttons/component/IEditButton.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/component/IEditButton.kt @@ -26,7 +26,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction interface IEditButton { val id: String - open suspend fun onInteraction( + suspend fun onInteraction( interaction: ButtonInteraction, response: PublicMessageInteractionResponseBehavior, guild: Guild, diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/AcceptEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/AcceptEditButton.kt new file mode 100644 index 0000000..4e04fa1 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/AcceptEditButton.kt @@ -0,0 +1,102 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.buttons.matchplanner + +import dev.kord.common.entity.Snowflake +import dev.kord.core.behavior.edit +import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User +import dev.kord.core.entity.channel.MessageChannel +import dev.kord.core.entity.interaction.ButtonInteraction +import dev.kord.rest.builder.message.modify.embed +import net.moonleay.lilJudd.Bot +import net.moonleay.lilJudd.buttons.component.IEditButton +import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository +import net.moonleay.lilJudd.util.EmbedUtil +import net.moonleay.lilJudd.util.Logger +import net.moonleay.lilJudd.util.MessageUtil + +class AcceptEditButton() : IEditButton { + override val id: String = "public.edit.btn.matchmanagement.accept" + + override suspend fun onInteraction( + interaction: ButtonInteraction, + response: PublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + val m = interaction.message + val eb = MessageUtil.getAClonedEmbed(m.embeds[0]) + var shouldEditButton = false + val mpdd = MatchPlanningDataRepository.getFromMessageInChannelInServer( + m.id.value.toLong(), + interaction.channelId.value.toLong(), + guild.id.value.toLong() + ) + if (mpdd == null) { + Logger.out("mpdd is null") + return + } + val role = guild.getRoleOrNull(Snowflake(mpdd.roleID)) + if (role == null) { + Logger.out("role is null") + return + } + val member = interaction.user.asMember(guild.id) ?: return + // do the checks and update + if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) { + if (member.roleIds.contains(Snowflake(mpdd.roleID))) { + Logger.out("Removing role from ${member.username}") + member.removeRole(role.id) + } + // remove the user from the 1st list in the embed + Logger.out("Removing ${user.username} from the 1st list in the embed") + eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 1).fields + shouldEditButton = true + } + if (m.embeds[0].fields[1].value.contains(user.id.value.toString())) { + Logger.out("Removing ${user.username} from the 2nd list in the embed") + eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 2).fields + shouldEditButton = true + } + if (!m.embeds[0].fields[0].value.contains(user.id.value.toString())) { + if (!member.roleIds.contains(Snowflake(mpdd.roleID))) { + Logger.out("Adding role to ${member.username}") + member.addRole(role.id) + } + //Add the user to the list in the embed + Logger.out("Adding ${user.username} to the 1st list in the embed") + eb.fields = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), eb, 1).fields + shouldEditButton = true + } + if (shouldEditButton) { + // update the message + Bot.bot.kordRef.getChannelOf(interaction.channelId)!!.getMessage(m.id).edit { + this.embed { + this.color = eb.color + this.title = eb.title + this.description = eb.description + this.fields = eb.fields + this.footer = eb.footer + } + } + } + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/CancelEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/CancelEditButton.kt index 3925cd3..348446c 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/CancelEditButton.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/CancelEditButton.kt @@ -28,12 +28,9 @@ import dev.kord.core.entity.interaction.ButtonInteraction import dev.kord.rest.builder.message.modify.embed import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.buttons.component.IEditButton -import net.moonleay.lilJudd.data.entry.MatchPlanningDataData -import net.moonleay.lilJudd.data.tables.MatchPlanningData +import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository import net.moonleay.lilJudd.util.EmbedUtil -import org.jetbrains.exposed.sql.and -import org.jetbrains.exposed.sql.select -import org.jetbrains.exposed.sql.transactions.transaction +import net.moonleay.lilJudd.util.Logger class CancelEditButton : IEditButton { override val id: String = "public.edit.btn.matchmanagement.cancel" @@ -46,35 +43,22 @@ class CancelEditButton : IEditButton { ) { val m = interaction.message if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) { - lateinit var mpdd: MatchPlanningDataData - var found = false - transaction { - for (pnr in MatchPlanningData.select { - MatchPlanningData.messageid eq (interaction.message.id.value.toString()) and ( - MatchPlanningData.serverid eq (guild.id.value.toString())) and ( - MatchPlanningData.channelid eq (interaction.channelId.value.toString())) - }) { - mpdd = MatchPlanningDataData( - pnr[MatchPlanningData.id].value, - pnr[MatchPlanningData.serverid], - pnr[MatchPlanningData.channelid], - pnr[MatchPlanningData.matchtype], - pnr[MatchPlanningData.registererid], - pnr[MatchPlanningData.roleid], - pnr[MatchPlanningData.opponentName], - pnr[MatchPlanningData.messageid], - pnr[MatchPlanningData.timestamp], - pnr[MatchPlanningData.jobstr] - ) - found = true - } - } - if (!found || mpdd == null) { + val mpdd = MatchPlanningDataRepository.getFromMessageInChannelInServer( + m.id.value.toLong(), + interaction.channelId.value.toLong(), + guild.id.value.toLong() + ) + if (mpdd == null) { + Logger.out("mpdd is null") + return + } + val role = guild.getRoleOrNull(Snowflake(mpdd.roleID)) + if (role == null) { + Logger.out("role is null") return } - val role = guild.getRoleOrNull(Snowflake(mpdd.roleid)) ?: return val member = interaction.user.asMember(guild.id) - if (member.roleIds.contains(Snowflake(mpdd.roleid))) { + if (member.roleIds.contains(Snowflake(mpdd.roleID))) { member.removeRole(role.id) } Bot.bot.kordRef.getChannelOf(interaction.channelId)!!.getMessage(m.id).edit { diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/DeclineEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/DeclineEditButton.kt new file mode 100644 index 0000000..93f6b36 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/DeclineEditButton.kt @@ -0,0 +1,102 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.buttons.matchplanner + +import dev.kord.common.entity.Snowflake +import dev.kord.core.behavior.edit +import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User +import dev.kord.core.entity.channel.MessageChannel +import dev.kord.core.entity.interaction.ButtonInteraction +import dev.kord.rest.builder.message.modify.embed +import net.moonleay.lilJudd.Bot +import net.moonleay.lilJudd.buttons.component.IEditButton +import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository +import net.moonleay.lilJudd.util.EmbedUtil +import net.moonleay.lilJudd.util.Logger +import net.moonleay.lilJudd.util.MessageUtil + +class DeclineEditButton : IEditButton { + override val id: String = "public.edit.btn.matchmanagement.decline" + + override suspend fun onInteraction( + interaction: ButtonInteraction, + response: PublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + val m = interaction.message + val eb = MessageUtil.getAClonedEmbed(m.embeds[0]) + var shouldEditButton = false + val mpdd = MatchPlanningDataRepository.getFromMessageInChannelInServer( + m.id.value.toLong(), + interaction.channelId.value.toLong(), + guild.id.value.toLong() + ) + if (mpdd == null) { + Logger.out("mpdd is null") + return + } + val role = guild.getRoleOrNull(Snowflake(mpdd.roleID)) + if (role == null) { + Logger.out("role is null") + return + } + val member = interaction.user.asMember(guild.id) ?: return + if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) { + if (member.roleIds.contains(Snowflake(mpdd.roleID))) { + Logger.out("Removing role from ${member.username}") + member.removeRole(role.id) + } + // remove the user from the 1st list in the embed + Logger.out("Removing ${user.username} from the 1st list in the embed") + eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 1).fields + shouldEditButton = true + } + if (!m.embeds[0].fields[1].value.contains(user.id.value.toString())) { + if (member.roleIds.contains(Snowflake(mpdd.roleID))) { + Logger.out("Removing role from ${member.username}") + member.removeRole(role.id) + } + // Add the user to the list in the embed + Logger.out("Adding ${user.username} to the 2nd list in the embed") + eb.fields = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), eb, 2).fields + shouldEditButton = true + } + if (m.embeds[0].fields[1].value.contains(user.id.value.toString())) { + // Remove the user from all tables + Logger.out("Removing ${user.username} from the 2nd list in the embed") + eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 2).fields + shouldEditButton = true + } + if (shouldEditButton) { + // update the message + Bot.bot.kordRef.getChannelOf(interaction.channelId)!!.getMessage(m.id).edit { + this.embed { + this.color = eb.color + this.title = eb.title + this.description = eb.description + this.fields = eb.fields + this.footer = eb.footer + } + } + } + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/SignMeUpEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/SignMeUpEditButton.kt deleted file mode 100644 index fa47749..0000000 --- a/src/main/kotlin/net/moonleay/lilJudd/buttons/matchplanner/SignMeUpEditButton.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * lilJudd - * Copyright (C) 2023 moonleay - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.moonleay.lilJudd.buttons.matchplanner - -import dev.kord.common.entity.Snowflake -import dev.kord.core.behavior.edit -import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior -import dev.kord.core.entity.Guild -import dev.kord.core.entity.User -import dev.kord.core.entity.channel.MessageChannel -import dev.kord.core.entity.interaction.ButtonInteraction -import dev.kord.rest.builder.message.modify.embed -import net.moonleay.lilJudd.Bot -import net.moonleay.lilJudd.buttons.component.IEditButton -import net.moonleay.lilJudd.data.entry.MatchPlanningDataData -import net.moonleay.lilJudd.data.tables.MatchPlanningData -import net.moonleay.lilJudd.util.EmbedUtil -import org.jetbrains.exposed.sql.and -import org.jetbrains.exposed.sql.select -import org.jetbrains.exposed.sql.transactions.transaction - -class SignMeUpEditButton() : IEditButton { - override val id: String = "public.edit.btn.matchmanagement.accept" - - override suspend fun onInteraction( - interaction: ButtonInteraction, - response: PublicMessageInteractionResponseBehavior, - guild: Guild, - user: User - ) { - val m = interaction.message - if (!m.embeds[0].fields[0].value.contains(user.id.value.toString())) { - lateinit var mpdd: MatchPlanningDataData - var found = false - transaction { - for (pnr in MatchPlanningData.select { - MatchPlanningData.messageid eq (interaction.message.id.value.toString()) and ( - MatchPlanningData.serverid eq (guild.id.value.toString())) and ( - MatchPlanningData.channelid eq (interaction.channelId.value.toString())) - }) { - mpdd = MatchPlanningDataData( - pnr[MatchPlanningData.id].value, - pnr[MatchPlanningData.serverid], - pnr[MatchPlanningData.channelid], - pnr[MatchPlanningData.matchtype], - pnr[MatchPlanningData.registererid], - pnr[MatchPlanningData.roleid], - pnr[MatchPlanningData.opponentName], - pnr[MatchPlanningData.messageid], - pnr[MatchPlanningData.timestamp], - pnr[MatchPlanningData.jobstr] - ) - found = true - } - } - if (!found || mpdd == null) { - return - } - val role = guild.getRoleOrNull(Snowflake(mpdd.roleid)) ?: return - val member = interaction.user.asMember(guild.id) - if (!member.roleIds.contains(Snowflake(mpdd.roleid))) { - member.addRole(role.id) - } - - //Add the user to the list in the embed - Bot.bot.kordRef.getChannelOf(interaction.channelId)!!.getMessage(m.id).edit { - this.embed { - val temp = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), m.embeds[0], 1) - this.color = temp.color - this.title = temp.title - this.description = temp.description - this.fields = temp.fields - this.footer = temp.footer - } - } - } - } -} diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/IsAvailableEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/IsAvailableEditButton.kt index 2acfe55..9dbae16 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/IsAvailableEditButton.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/IsAvailableEditButton.kt @@ -27,6 +27,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction import dev.kord.rest.builder.message.modify.embed import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.buttons.component.IEditButton +import net.moonleay.lilJudd.features.AvailabilityManager import net.moonleay.lilJudd.util.EmbedUtil class IsAvailableEditButton : IEditButton { @@ -62,5 +63,6 @@ class IsAvailableEditButton : IEditButton { } } } + AvailabilityManager.updateInChannel(interaction.channelId) } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/MaybeAvailableEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/MaybeAvailableEditButton.kt index 3696a54..01cf792 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/MaybeAvailableEditButton.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/MaybeAvailableEditButton.kt @@ -27,6 +27,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction import dev.kord.rest.builder.message.modify.embed import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.buttons.component.IEditButton +import net.moonleay.lilJudd.features.AvailabilityManager import net.moonleay.lilJudd.util.EmbedUtil class MaybeAvailableEditButton : IEditButton { @@ -62,5 +63,6 @@ class MaybeAvailableEditButton : IEditButton { } } } + AvailabilityManager.updateInChannel(interaction.channelId) } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/NotAvailableEditButton.kt b/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/NotAvailableEditButton.kt index 698993f..ade9557 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/NotAvailableEditButton.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/buttons/timeplanner/NotAvailableEditButton.kt @@ -27,6 +27,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction import dev.kord.rest.builder.message.modify.embed import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.buttons.component.IEditButton +import net.moonleay.lilJudd.features.AvailabilityManager import net.moonleay.lilJudd.util.EmbedUtil class NotAvailableEditButton : IEditButton { @@ -62,5 +63,6 @@ class NotAvailableEditButton : IEditButton { } } } + AvailabilityManager.updateInChannel(interaction.channelId) } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/Splatoon3Api.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/Splatoon3Api.kt new file mode 100644 index 0000000..b0192e5 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/Splatoon3Api.kt @@ -0,0 +1,117 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api + +import net.moonleay.lilJudd.data.api.entry.schedule.ModeData +import net.moonleay.lilJudd.util.TimeUtil + +object Splatoon3Api { + private fun getRegularMode(timestamp: Long): ModeData { + Splatoon3ApiCache.cachedRegularModeData.map { modeData -> + val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC") + val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC") + if (timestamp in startTime..endTime) { + return modeData + } + } + throw Exception("No current mode found") + } + + private fun getOpenMode(timestamp: Long): ModeData { + Splatoon3ApiCache.cachedCompetitiveOpenModeData.map { modeData -> + val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC") + val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC") + if (timestamp in startTime..endTime) { + return modeData + } + } + throw Exception("No current mode found") + } + + private fun getXMode(timestamp: Long): ModeData { + Splatoon3ApiCache.cachedXModeData.map { modeData -> + val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC") + val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC") + if (timestamp in startTime..endTime) { + return modeData + } + } + throw Exception("No current mode found") + } + + private fun getSeriesMode(timestamp: Long): ModeData { + Splatoon3ApiCache.cachedCompetitiveSeriesModeData.map { modeData -> + val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC") + val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC") + if (timestamp in startTime..endTime) { + return modeData + } + } + throw Exception("No current mode found") + } + + fun getRegularMapsFormatted(timestamp: Long): String { + val modeData = getRegularMode(timestamp) + val map1 = modeData.map1!!.name.split(" ")[0] + val map2 = modeData.map2!!.name.split(" ")[0] + return "R: $map1 & $map2" + } + + fun getOpenModeFormatted(timestamp: Long): String { + val modeData = getOpenMode(timestamp) + val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC") + val diffStamp = TimeUtil.getTimeDifferenceFormatted(System.currentTimeMillis(), endTime) + return "O: ${modeData.ruleSetName} $diffStamp left" + } + + fun getOpenMapFormatted(timestamp: Long): String { + val modeData = getOpenMode(timestamp) + val map1 = modeData.map1!!.name.split(" ")[0] + val map2 = modeData.map2!!.name.split(" ")[0] + return "O: $map1 & $map2" + } + + fun getSeriesModeFormatted(timestamp: Long): String { + val modeData = getSeriesMode(timestamp) + val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC") + val diffStamp = TimeUtil.getTimeDifferenceFormatted(System.currentTimeMillis(), endTime) + return "S: ${modeData.ruleSetName} $diffStamp left" + } + + fun getSeriesMapsFormatted(timestamp: Long): String { + val modeData = getSeriesMode(timestamp) + val map1 = modeData.map1!!.name.split(" ")[0] + val map2 = modeData.map2!!.name.split(" ")[0] + return "S: $map1 & $map2" + } + + fun getXModeFormatted(timestamp: Long): String { + val modeData = getXMode(timestamp) + val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC") + val diffStamp = TimeUtil.getTimeDifferenceFormatted(System.currentTimeMillis(), endTime) + return "X: ${modeData.ruleSetName} $diffStamp left" + } + + fun getXMapFormatted(timestamp: Long): String { + val modeData = getXMode(timestamp) + val map1 = modeData.map1!!.name.split(" ")[0] + val map2 = modeData.map2!!.name.split(" ")[0] + return "X: $map1 & $map2" + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/Splatoon3ApiCache.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/Splatoon3ApiCache.kt new file mode 100644 index 0000000..714ff1e --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/Splatoon3ApiCache.kt @@ -0,0 +1,535 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api + +import io.ktor.http.* +import kotlinx.serialization.json.* +import net.moonleay.lilJudd.data.api.entry.coop.CoopGearData +import net.moonleay.lilJudd.data.api.entry.schedule.* +import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestColor +import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestData +import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestTeamData +import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestTeamResults +import net.moonleay.lilJudd.data.api.entry.splatnet.BrandData +import net.moonleay.lilJudd.data.api.entry.splatnet.GearAbilityData +import net.moonleay.lilJudd.data.api.entry.splatnet.SplatnetItemData +import net.moonleay.lilJudd.data.api.type.ApiDataType +import net.moonleay.lilJudd.data.api.type.ApiRequestType +import net.moonleay.lilJudd.util.Logger +import net.moonleay.lilJudd.util.NetUtil +import net.moonleay.liljudd.build.BuildConstants + +object Splatoon3ApiCache { + private val user_agent = + "lilJudd/${BuildConstants.version} (${System.getProperty("os.name")}/${System.getProperty("os.version")}) [contact@moonleay.net]" + private val base_url = "https://splatoon3.ink/data/" // Thank god there is an API + + internal var cachedSplatfestData = mutableListOf() + internal var cachedMapData = mutableMapOf() + internal var cachedRegularModeData = mutableListOf() + internal var cachedCompetitiveSeriesModeData = mutableListOf() + internal var cachedCompetitiveOpenModeData = mutableListOf() + internal var cachedXModeData = mutableListOf() + internal var cachedChallengesData = mutableListOf() + internal var cachedShiftData = mutableListOf() + internal var cachedBigRunShiftData = mutableListOf() + internal var cachedCoopRewardsData = mutableListOf() + internal var cachedSplatnetItemData = mutableListOf() + internal var cachedSplatnetLimitedItemData = mutableListOf() + internal lateinit var splatnetShopBrandData: BrandData + internal lateinit var splatnetShopNextBrandData: BrandData + fun updateData(dataType: ApiDataType, requestType: ApiRequestType) { + Logger.out("Updating data for $dataType with USER-AGENT: $user_agent") + Logger.out("Reason for update: $requestType") + when (dataType) { + ApiDataType.SCHEDULES -> { + updateScheduleCache(user_agent) + } + + ApiDataType.SPLATNETGEAR -> { + updateSplatnetGearCache(user_agent) + } + + ApiDataType.COOP -> { + updateCOOPCache(user_agent) + } + + ApiDataType.SPLATFESTS -> { + updateSplatfestCache(user_agent) + } + + ApiDataType.ALL -> { + updateScheduleCache(user_agent) + updateSplatnetGearCache(user_agent) + updateSplatfestCache(user_agent) + updateCOOPCache(user_agent) + } + } + Logger.out("Finished updating data for $dataType") + } + + private fun updateSplatnetGearCache(uag: String) { + val apiResponse = NetUtil.GETJsonData("${base_url}gear.json", uag) + if (apiResponse.startsWith("Error")) { + Logger.out("Error getting splatnet data: $apiResponse") + return + } + val json = Json.parseToJsonElement(apiResponse) + val pickupBrandData = json.jsonObject["data"]!!.jsonObject["gesotown"]!!.jsonObject["pickupBrand"]!!.jsonObject + + val brand = pickupBrandData["brand"]!!.jsonObject + splatnetShopBrandData = + BrandData( + brand["name"]!!.jsonPrimitive.content, + Url(pickupBrandData["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + GearAbilityData( + brand["usualGearPower"]!!.jsonObject["name"]!!.jsonPrimitive.content, + brand["usualGearPower"]!!.jsonObject["desc"]!!.jsonPrimitive.content, + Url(brand["usualGearPower"]!!.jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + pickupBrandData["saleEndTime"]!!.jsonPrimitive.content + ) + val nextBrand = pickupBrandData["nextBrand"]!!.jsonObject + splatnetShopNextBrandData = + BrandData( + nextBrand["name"]!!.jsonPrimitive.content, + Url(pickupBrandData["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + null, + null + ) + cachedSplatnetItemData = mutableListOf() + val items = pickupBrandData["brandGears"]!!.jsonArray + items.forEach { + val obj = it as JsonObject + val gear = it["gear"]!!.jsonObject + val primaryGearPower = gear["primaryGearPower"]!!.jsonObject + val additionalGearPowers = gear["additionalGearPowers"]!!.jsonArray + val additionalGearPowersList = mutableListOf() + additionalGearPowers.forEach { + val ob = it as JsonObject + additionalGearPowersList.add( + GearAbilityData( + ob["name"]!!.jsonPrimitive.content, + null, + Url(ob["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ) + ) + } + cachedSplatnetItemData.add( + SplatnetItemData( + obj["saleEndTime"]!!.jsonPrimitive.content, + obj["price"]!!.jsonPrimitive.int, + gear["__typename"]!!.jsonPrimitive.content, + gear["name"]!!.jsonPrimitive.content, + GearAbilityData( + primaryGearPower["name"]!!.jsonPrimitive.content, + null, + Url(primaryGearPower["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + additionalGearPowersList, + Url(gear["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + splatnetShopBrandData + ) + ) + } + Logger.out("Updated gear data") + + val limitedItemData = json.jsonObject["data"]!!.jsonObject["gesotown"]!!.jsonObject["limitedGears"]!!.jsonArray + cachedSplatnetLimitedItemData = mutableListOf() + limitedItemData.forEach { + val obj = it as JsonObject + val gear = obj["gear"]!!.jsonObject + val additionalGearPowers = gear["additionalGearPowers"]!!.jsonArray + val additionalGearPowersList = mutableListOf() + additionalGearPowers.forEach { + val ob = it as JsonObject + additionalGearPowersList.add( + GearAbilityData( + ob["name"]!!.jsonPrimitive.content, + null, + Url(ob["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ) + ) + } + cachedSplatnetLimitedItemData.add( + SplatnetItemData( + obj["saleEndTime"]!!.jsonPrimitive.content, + obj["price"]!!.jsonPrimitive.int, + gear["__typename"]!!.jsonPrimitive.content, + gear["name"]!!.jsonPrimitive.content, + GearAbilityData( + gear["primaryGearPower"]!!.jsonObject["name"]!!.jsonPrimitive.content, + null, + Url(gear["primaryGearPower"]!!.jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + additionalGearPowersList, + Url(gear["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + splatnetShopBrandData + ) + ) + } + } + + private fun updateCOOPCache(uag: String) { + val apiResponse = NetUtil.GETJsonData("${base_url}coop.json", uag) + if (apiResponse.startsWith("Error")) { + Logger.out("Error getting coop data: $apiResponse") + return + } + val json = Json.parseToJsonElement(apiResponse) + val data = json.jsonObject["data"]!!.jsonObject["coopResult"]!!.jsonObject["monthlyGear"]!!.jsonObject + cachedCoopRewardsData = mutableListOf() + cachedCoopRewardsData.add( + CoopGearData( + data["name"]!!.jsonPrimitive.content, + Url(data["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + data["__typename"]!!.jsonPrimitive.content + ) + ) + Logger.out("Updated COOP data") + } + + private fun updateScheduleCache(uag: String) { + val apiResponse = NetUtil.GETJsonData("${base_url}schedules.json", uag) + if (apiResponse.startsWith("Error")) { + Logger.out("Error getting schedule data: $apiResponse") + return + } + val json = Json.decodeFromString(apiResponse) as JsonObject + val data = json["data"]!!.jsonObject + + val mapList = data["vsStages"]!!.jsonObject["nodes"]!!.jsonArray + cachedMapData = mutableMapOf() + mapList.forEach { + val obj = it as JsonObject + val imageURL = Url(obj.jsonObject["originalImage"]!!.jsonObject["url"]!!.jsonPrimitive.content) + val id = obj.jsonObject["vsStageId"]!!.jsonPrimitive.int + cachedMapData[id] = MapData( + id, + imageURL, + it.jsonObject["name"]!!.jsonPrimitive.content + ) + } + Logger.out("Updated maplist data") + + val regularMatches = data["regularSchedules"]!!.jsonObject["nodes"]!!.jsonArray + cachedRegularModeData = mutableListOf() + regularMatches.forEach { + val obj = it as JsonObject + val setting = obj["regularMatchSetting"]!!.jsonObject + cachedRegularModeData.add( + ModeData( + obj["startTime"]!!.jsonPrimitive.content, + obj["endTime"]!!.jsonPrimitive.content, + setting["__typename"]!!.jsonPrimitive.content, + cachedMapData[setting["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int], + cachedMapData[setting["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int], + setting["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content, + setting["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content, + "TURF_WAR" + ) + ) + } + Logger.out("Updated Regular match data") + + val compMatches = data["bankaraSchedules"]!!.jsonObject["nodes"]!!.jsonArray + cachedCompetitiveSeriesModeData = mutableListOf() + cachedCompetitiveOpenModeData = mutableListOf() + compMatches.forEach { + val obj = it as JsonObject + val setting = obj["bankaraMatchSettings"]!!.jsonArray + setting.forEach { + val ob = it as JsonObject + val mode = ob["bankaraMode"]!!.jsonPrimitive.content + if (mode == "CHALLENGE") { + cachedCompetitiveSeriesModeData.add( + ModeData( + obj["startTime"]!!.jsonPrimitive.content, + obj["endTime"]!!.jsonPrimitive.content, + ob["__typename"]!!.jsonPrimitive.content, + cachedMapData[ob["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int], + cachedMapData[ob["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int], + ob["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content, + ob["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content, + mode + ) + ) + } else if (mode == "OPEN") { + cachedCompetitiveOpenModeData.add( + ModeData( + obj["startTime"]!!.jsonPrimitive.content, + obj["endTime"]!!.jsonPrimitive.content, + ob["__typename"]!!.jsonPrimitive.content, + cachedMapData[ob["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int], + cachedMapData[ob["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int], + ob["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content, + ob["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content, + mode + ) + ) + } + } + } + Logger.out("Updated Competitive match data") + + val xMatches = data["xSchedules"]!!.jsonObject["nodes"]!!.jsonArray + cachedXModeData = mutableListOf() + xMatches.forEach { + val obj = it as JsonObject + val setting = obj["xMatchSetting"]!!.jsonObject + cachedXModeData.add( + ModeData( + obj["startTime"]!!.jsonPrimitive.content, + obj["endTime"]!!.jsonPrimitive.content, + setting["__typename"]!!.jsonPrimitive.content, + cachedMapData[setting["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int], + cachedMapData[setting["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int], + setting["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content, + setting["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content, + "X" + ) + ) + } + Logger.out("Updated X match data") + + val challengeData = data["eventSchedules"]!!.jsonObject["nodes"]!!.jsonArray + cachedChallengesData = mutableListOf() + challengeData.forEach { + val obj = it as JsonObject + val tpd = obj["timePeriods"]!!.jsonArray + val setting = obj["leagueMatchSetting"]!!.jsonObject + val event = setting["leagueMatchEvent"]!!.jsonObject + cachedChallengesData.add( + ChallengeModeData( + event["leagueMatchEventId"]!!.jsonPrimitive.content, + event["name"]!!.jsonPrimitive.content, + event["desc"]!!.jsonPrimitive.content, + event["regulation"]!!.jsonPrimitive.content, + cachedMapData[setting["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int], + cachedMapData[setting["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int], + setting["__typename"]!!.jsonPrimitive.content, + setting["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content, + setting["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content, + TimePeriodData( + tpd[0].jsonObject["startTime"]!!.jsonPrimitive.content, + tpd[0].jsonObject["endTime"]!!.jsonPrimitive.content + ), + TimePeriodData( + tpd[1].jsonObject["startTime"]!!.jsonPrimitive.content, + tpd[1].jsonObject["endTime"]!!.jsonPrimitive.content + ), + TimePeriodData( + tpd[2].jsonObject["startTime"]!!.jsonPrimitive.content, + tpd[2].jsonObject["endTime"]!!.jsonPrimitive.content + ) + ) + ) + } + Logger.out("Updated Challenge data") + + val shiftData = data["coopGroupingSchedule"]!!.jsonObject["regularSchedules"]!!.jsonObject["nodes"]!!.jsonArray + cachedShiftData = mutableListOf() + shiftData.forEach { + val obj = it as JsonObject + val setting = obj["setting"]!!.jsonObject + val stage = setting["coopStage"]!!.jsonObject + val weapons = setting["weapons"]!!.jsonArray + cachedShiftData.add( + ShiftData( + obj["startTime"]!!.jsonPrimitive.content, + obj["endTime"]!!.jsonPrimitive.content, + obj["__splatoon3ink_king_salmonid_guess"]!!.jsonPrimitive.content, + setting["__typename"]!!.jsonPrimitive.content, + stage["name"]!!.jsonPrimitive.content, + Url(stage["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + WeaponData( + weapons[0].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[0].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + WeaponData( + weapons[1].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[1].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + WeaponData( + weapons[2].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[2].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + WeaponData( + weapons[3].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[3].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ) + ) + ) + } + + val bigRunData = data["coopGroupingSchedule"]!!.jsonObject["bigRunSchedules"]!!.jsonObject["nodes"]!!.jsonArray + cachedBigRunShiftData = mutableListOf() + bigRunData.forEach { + val obj = it as JsonObject + val setting = obj["setting"]!!.jsonObject + val stage = setting["coopStage"]!!.jsonObject + val weapons = setting["weapons"]!!.jsonArray + cachedBigRunShiftData.add( + ShiftData( + obj["startTime"]!!.jsonPrimitive.content, + obj["endTime"]!!.jsonPrimitive.content, + obj["__splatoon3ink_king_salmonid_guess"]!!.jsonPrimitive.content, + setting["__typename"]!!.jsonPrimitive.content, + stage["name"]!!.jsonPrimitive.content, + Url(stage["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + WeaponData( + weapons[0].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[0].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + WeaponData( + weapons[1].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[1].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + WeaponData( + weapons[2].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[2].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ), + WeaponData( + weapons[3].jsonObject["name"]!!.jsonPrimitive.content, + Url(weapons[3].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content) + ) + ) + ) + } + Logger.out("Updated big run data") + + Logger.out("Updated all Schedules") + } + + private fun updateSplatfestCache(uag: String) { + val apiResponse = NetUtil.GETJsonData("${base_url}festivals.json", uag) + if (apiResponse.startsWith("Error")) { + Logger.out("Error getting splatfest data: $apiResponse") + return + } + val json = Json.decodeFromString(apiResponse) as JsonObject + val festivals = json["US"]!!.jsonObject["data"]!!.jsonObject["festRecords"]!!.jsonObject["nodes"]!!.jsonArray + cachedSplatfestData = mutableListOf() + festivals.forEach { + val fest = it as JsonObject + val teams = fest.jsonObject["teams"]!!.jsonArray + val team1 = teams[0].jsonObject + val team1Color = team1["color"]!!.jsonObject + var team1Result: JsonObject? = null + if (team1["result"] !is JsonNull) { + team1Result = team1["result"]!!.jsonObject + } + val team2 = teams[1].jsonObject + val team2Color = team2["color"]!!.jsonObject + var team2Result: JsonObject? = null + if (team2["result"] !is JsonNull) { + team2Result = team2["result"]!!.jsonObject + } + val team3 = teams[2].jsonObject + val team3Color = team3["color"]!!.jsonObject + var team3Result: JsonObject? = null + if (team3["result"] !is JsonNull) { + team3Result = team3["result"]!!.jsonObject + } + cachedSplatfestData.add( + SplatfestData( + fest.jsonObject["id"]!!.jsonPrimitive.content, + fest.jsonObject["state"]!!.jsonPrimitive.content, + fest.jsonObject["startTime"]!!.jsonPrimitive.content, + fest.jsonObject["endTime"]!!.jsonPrimitive.content, + fest.jsonObject["title"]!!.jsonPrimitive.content, + Url(fest.jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content), + SplatfestTeamData( + team1["teamName"]!!.jsonPrimitive.content, + SplatfestColor( + team1Color["a"]!!.jsonPrimitive.int, + team1Color["b"]!!.jsonPrimitive.double, + team1Color["g"]!!.jsonPrimitive.double, + team1Color["r"]!!.jsonPrimitive.double + ), + if (team1Result.isNullOrEmpty() || team1Result["tricolorContributionRatio"]!!.jsonPrimitive.doubleOrNull == null) + null + else SplatfestTeamResults( + team1Result["isWinner"]!!.jsonPrimitive.boolean, + team1Result["horagaiRatio"]!!.jsonPrimitive.double, + team1Result["isHoragaiRatioTop"]!!.jsonPrimitive.boolean, + team1Result["voteRatio"]!!.jsonPrimitive.double, + team1Result["isVoteRatioTop"]!!.jsonPrimitive.boolean, + team1Result["regularContributionRatio"]!!.jsonPrimitive.double, + team1Result["isRegularContributionRatioTop"]!!.jsonPrimitive.boolean, + team1Result["challengeContributionRatio"]!!.jsonPrimitive.double, + team1Result["isChallengeContributionRatioTop"]!!.jsonPrimitive.boolean, + team1Result["tricolorContributionRatio"]!!.jsonPrimitive.double, + team1Result["isTricolorContributionRatioTop"]!!.jsonPrimitive.boolean, + ) + ), + SplatfestTeamData( + team2["teamName"]!!.jsonPrimitive.content, + SplatfestColor( + team2Color["a"]!!.jsonPrimitive.int, + team2Color["b"]!!.jsonPrimitive.double, + team2Color["g"]!!.jsonPrimitive.double, + team2Color["r"]!!.jsonPrimitive.double + ), + if (team2Result.isNullOrEmpty() || team2Result["tricolorContributionRatio"]!!.jsonPrimitive.doubleOrNull == null) + null + else SplatfestTeamResults( + team2Result["isWinner"]!!.jsonPrimitive.boolean, + team2Result["horagaiRatio"]!!.jsonPrimitive.double, + team2Result["isHoragaiRatioTop"]!!.jsonPrimitive.boolean, + team2Result["voteRatio"]!!.jsonPrimitive.double, + team2Result["isVoteRatioTop"]!!.jsonPrimitive.boolean, + team2Result["regularContributionRatio"]!!.jsonPrimitive.double, + team2Result["isRegularContributionRatioTop"]!!.jsonPrimitive.boolean, + team2Result["challengeContributionRatio"]!!.jsonPrimitive.double, + team2Result["isChallengeContributionRatioTop"]!!.jsonPrimitive.boolean, + team2Result["tricolorContributionRatio"]!!.jsonPrimitive.double, + team2Result["isTricolorContributionRatioTop"]!!.jsonPrimitive.boolean, + ) + ), + SplatfestTeamData( + team3["teamName"]!!.jsonPrimitive.content, + SplatfestColor( + team3Color["a"]!!.jsonPrimitive.int, + team3Color["b"]!!.jsonPrimitive.double, + team3Color["g"]!!.jsonPrimitive.double, + team3Color["r"]!!.jsonPrimitive.double + ), + if (team3Result.isNullOrEmpty() || team3Result["tricolorContributionRatio"]!!.jsonPrimitive.doubleOrNull == null) + null + else SplatfestTeamResults( + team3Result["isWinner"]!!.jsonPrimitive.boolean, + team3Result["horagaiRatio"]!!.jsonPrimitive.double, + team3Result["isHoragaiRatioTop"]!!.jsonPrimitive.boolean, + team3Result["voteRatio"]!!.jsonPrimitive.double, + team3Result["isVoteRatioTop"]!!.jsonPrimitive.boolean, + team3Result["regularContributionRatio"]!!.jsonPrimitive.double, + team3Result["isRegularContributionRatioTop"]!!.jsonPrimitive.boolean, + team3Result["challengeContributionRatio"]!!.jsonPrimitive.double, + team3Result["isChallengeContributionRatioTop"]!!.jsonPrimitive.boolean, + team3Result["tricolorContributionRatio"]!!.jsonPrimitive.double, + team3Result["isTricolorContributionRatioTop"]!!.jsonPrimitive.boolean, + ) + ), + ) + ) + } + Logger.out("Updated Splatfest data") + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/coop/CoopGearData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/coop/CoopGearData.kt new file mode 100644 index 0000000..4f46642 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/coop/CoopGearData.kt @@ -0,0 +1,28 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.coop + +import io.ktor.http.* + +data class CoopGearData( + val name: String, + val image: Url, + val __typename: String, + + ) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ChallengeModeData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ChallengeModeData.kt new file mode 100644 index 0000000..c288fe9 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ChallengeModeData.kt @@ -0,0 +1,34 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.schedule + +data class ChallengeModeData( + val leagueMatchEventId: String, + val name: String, + val description: String, + val regulation: String, + val map1: MapData?, + val map2: MapData?, + val __typename: String, + val ruleSet: String, + val ruleSetName: String, + val timePeriod1: TimePeriodData, + val timePeriod2: TimePeriodData, + val timePeriod3: TimePeriodData, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/MapData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/MapData.kt new file mode 100644 index 0000000..422783c --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/MapData.kt @@ -0,0 +1,27 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.schedule + +import io.ktor.http.* + +data class MapData( + val stageID: Int, + val image: Url, + val name: String, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ModeData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ModeData.kt new file mode 100644 index 0000000..8295a1a --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ModeData.kt @@ -0,0 +1,30 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.schedule + +data class ModeData( + val startTime: String, + val endTime: String, + val matchType: String, + val map1: MapData?, + val map2: MapData?, + val ruleSetName: String, + val ruleSet: String, + val mode: String, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ShiftData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ShiftData.kt new file mode 100644 index 0000000..a4d28ae --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/ShiftData.kt @@ -0,0 +1,34 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.schedule + +import io.ktor.http.* + +data class ShiftData( + val startTime: String, + val endTime: String, + val __splatoon3ink_king_salmonid_guess: String, + val __typename: String, + val stageName: String, + val image: Url, + val weapon1: WeaponData, + val weapon2: WeaponData, + val weapon3: WeaponData, + val weapon4: WeaponData, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/TimePeriodData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/TimePeriodData.kt new file mode 100644 index 0000000..53edb96 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/TimePeriodData.kt @@ -0,0 +1,24 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.schedule + +data class TimePeriodData( + val startTime: String, + val endTime: String, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/WeaponData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/WeaponData.kt new file mode 100644 index 0000000..997a24b --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/schedule/WeaponData.kt @@ -0,0 +1,26 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.schedule + +import io.ktor.http.* + +data class WeaponData( + val name: String, + val image: Url, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestColor.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestColor.kt new file mode 100644 index 0000000..391ccb3 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestColor.kt @@ -0,0 +1,26 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.splatfest + +data class SplatfestColor( + val a: Int, + val b: Double, + val g: Double, + val r: Double, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifierRoles.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestData.kt similarity index 67% rename from src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifierRoles.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestData.kt index d8d3b9d..f52b9b4 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifierRoles.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestData.kt @@ -16,13 +16,18 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data.tables +package net.moonleay.lilJudd.data.api.entry.splatfest -import org.jetbrains.exposed.dao.id.IntIdTable +import io.ktor.http.* -object PlanningNotifierRoles : IntIdTable() { - var serverid = varchar("serverid", 50) - var channelid = varchar("channelid", 50) - var hastimeroleid = varchar("hastimeroleid", 50) - var wantstobenotifiedid = varchar("wantstobenotifiedid", 50) -} +data class SplatfestData( + val id: String, + val state: String, + val startTime: String, + val endTime: String, + val title: String, + val image: Url, + val team1: SplatfestTeamData, + val team2: SplatfestTeamData, + val team3: SplatfestTeamData, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestTeamData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestTeamData.kt new file mode 100644 index 0000000..9ea2e72 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestTeamData.kt @@ -0,0 +1,25 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.splatfest + +data class SplatfestTeamData( + val teamName: String, + val color: SplatfestColor, + val results: SplatfestTeamResults?, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestTeamResults.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestTeamResults.kt new file mode 100644 index 0000000..4888adc --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatfest/SplatfestTeamResults.kt @@ -0,0 +1,33 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.splatfest + +data class SplatfestTeamResults( + val isWinner: Boolean, + val horagaiRatio: Double, + val horagaiRatioTop: Boolean, + val voteRatio: Double, + val voteRatioTop: Boolean, + val regularRatio: Double, + val regularRatioTop: Boolean, + val challengeRatio: Double, + val challengeRatioTop: Boolean, + val tricolorRatio: Double, + val tricolorRatioTop: Boolean, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/BrandData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/BrandData.kt new file mode 100644 index 0000000..6781172 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/BrandData.kt @@ -0,0 +1,28 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.splatnet + +import io.ktor.http.* + +data class BrandData( + val name: String, + val image: Url, + val usualGearPower: GearAbilityData?, + val saleEndTime: String?, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/GearAbilityData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/GearAbilityData.kt new file mode 100644 index 0000000..713d946 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/GearAbilityData.kt @@ -0,0 +1,27 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.splatnet + +import io.ktor.http.* + +data class GearAbilityData( + val name: String, + val description: String?, + val image: Url, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/SplatnetItemData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/SplatnetItemData.kt new file mode 100644 index 0000000..43df20b --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/entry/splatnet/SplatnetItemData.kt @@ -0,0 +1,32 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.entry.splatnet + +import io.ktor.http.* + +data class SplatnetItemData( + val saleEndTime: String, + val price: Int, + val typeName: String, + val name: String, + val primaryGearPower: GearAbilityData, + val additionalGearPowers: List, + val image: Url, + val brand: BrandData, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/type/ApiDataType.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/type/ApiDataType.kt new file mode 100644 index 0000000..7123b0d --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/type/ApiDataType.kt @@ -0,0 +1,27 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.type + +enum class ApiDataType { + SCHEDULES, + SPLATNETGEAR, + COOP, + SPLATFESTS, + ALL +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/api/type/ApiRequestType.kt b/src/main/kotlin/net/moonleay/lilJudd/data/api/type/ApiRequestType.kt new file mode 100644 index 0000000..da20371 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/api/type/ApiRequestType.kt @@ -0,0 +1,26 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.api.type + +enum class ApiRequestType(val nameToDisplay: String) { + AUTOMATIC_CACHE_UPDATE("automatic request to update the cache"), + AUTOMATIC_CACHE_CREATION_AT_STARTUP("automatic request to create cache at startup"), + MANUAL("manual request"), + DEBUG("debug request") +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/DB.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/DB.kt similarity index 56% rename from src/main/kotlin/net/moonleay/lilJudd/data/DB.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/database/DB.kt index b1ff4b7..7c58ea0 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/DB.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/DB.kt @@ -16,13 +16,21 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data +package net.moonleay.lilJudd.data.database +import net.moonleay.lilJudd.data.database.tables.MatchPlanningData +import net.moonleay.lilJudd.data.database.tables.PlanningNotifierRoles +import net.moonleay.lilJudd.data.database.tables.TimePlanningChannels +import net.moonleay.lilJudd.data.database.tables.TimePlanningMessages import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.sql.SchemaUtils +import org.jetbrains.exposed.sql.transactions.transaction object DB { - //Connect to the provided DB; trows errors, if the DB is not avalible. + private var connected = false + + //Connect to the provided DB; trows errors, if the DB is not available. fun connect(dbDomain: String, dbName: String, dbUser: String, dbPasswd: String) { Database.connect( "jdbc:postgresql://$dbDomain/$dbName", @@ -30,5 +38,18 @@ object DB { user = dbUser, password = dbPasswd ) + connected = true + } + + fun register() { + if (!connected) + return + // Register tables here + transaction { + SchemaUtils.create(TimePlanningChannels) + SchemaUtils.create(TimePlanningMessages) + SchemaUtils.create(MatchPlanningData) + SchemaUtils.create(PlanningNotifierRoles) + } } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/entry/MatchPlanningDataData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/MatchPlanningDataData.kt similarity index 72% rename from src/main/kotlin/net/moonleay/lilJudd/data/entry/MatchPlanningDataData.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/database/entry/MatchPlanningDataData.kt index ca0bd32..b19c5e7 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/entry/MatchPlanningDataData.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/MatchPlanningDataData.kt @@ -16,17 +16,17 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data.entry +package net.moonleay.lilJudd.data.database.entry data class MatchPlanningDataData( val id: Int, - val serverid: String, - val channelid: String, - val matchtype: String, - val registererid: String, - val roleid: String, - val opponentname: String, - val messageid: String, - val timestamp: String, - val jobstr: String + val serverID: Long, + val channelID: Long, + val matchType: String, + val registererID: Long, + val roleID: Long, + val opponentName: String, + val messageID: Long, + val timestamp: Long, + val jobString: String ) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/entry/PlanningNotifierRolesData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/PlanningNotifierRolesData.kt similarity index 68% rename from src/main/kotlin/net/moonleay/lilJudd/data/entry/PlanningNotifierRolesData.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/database/entry/PlanningNotifierRolesData.kt index 8cba107..c58130a 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/entry/PlanningNotifierRolesData.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/PlanningNotifierRolesData.kt @@ -16,11 +16,12 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data.entry +package net.moonleay.lilJudd.data.database.entry data class PlanningNotifierRolesData( - val serverID: String, // The id of the server - val channelId: String, // The id of the channel - val hastimeroleid: String, // The id of the role that has time today - val wantstobenotifid: String // The id of the role that wants to be notified + val id: Int, // The id of the entry + val serverID: Long, // The id of the server + val channelID: Long, // The id of the channel + val hasTimeRoleID: Long, // The id of the role that has time today + val wantsToBeNotifiedID: Long // The id of the role that wants to be notified ) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/TimePlanningChannelsData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/TimePlanningChannelsData.kt new file mode 100644 index 0000000..7edd496 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/TimePlanningChannelsData.kt @@ -0,0 +1,25 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.database.entry + +data class TimePlanningChannelsData( + val id: Int, + val serverID: Long, + val channelID: Long, +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/entry/TimePlanningMessagesData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/TimePlanningMessagesData.kt similarity index 70% rename from src/main/kotlin/net/moonleay/lilJudd/data/entry/TimePlanningMessagesData.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/database/entry/TimePlanningMessagesData.kt index 3da4ba8..3126e2c 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/entry/TimePlanningMessagesData.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/entry/TimePlanningMessagesData.kt @@ -16,11 +16,12 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data.entry +package net.moonleay.lilJudd.data.database.entry data class TimePlanningMessagesData( - val serverid: String, // The discord server id - val channelid: String, // The discord channel id - val weekstamp: String, // The timestamp of the monday of the week at 4am UTC - val messageids: String // IDs are in the following format: "{weekdayNr}:{id};{weekdayNr}:{id};[etc.]" + val id: Int, // The id of the entry + val serverID: Long, // The discord server id + val channelID: Long, // The discord channel id + val weekstamp: Long, // The timestamp of the monday of the week at 4am UTC + val messageIDs: String // IDs are in the following format: "{weekdayNr}:{id};{weekdayNr}:{id};[etc.]" ) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/MatchPlanningDataRepository.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/MatchPlanningDataRepository.kt new file mode 100644 index 0000000..84a1e66 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/MatchPlanningDataRepository.kt @@ -0,0 +1,112 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.database.repository + +import net.moonleay.lilJudd.data.database.entry.MatchPlanningDataData +import net.moonleay.lilJudd.data.database.tables.MatchPlanningData +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.transactions.transaction + +object MatchPlanningDataRepository { + + fun getAll(): List { + val dataList = mutableListOf() + transaction { + MatchPlanningData.selectAll().forEach { + dataList.add( + MatchPlanningDataData( + it[MatchPlanningData.id], + it[MatchPlanningData.serverid], + it[MatchPlanningData.channelid], + it[MatchPlanningData.matchtype], + it[MatchPlanningData.registererid], + it[MatchPlanningData.roleid], + it[MatchPlanningData.opponentName], + it[MatchPlanningData.messageid], + it[MatchPlanningData.timestamp], + it[MatchPlanningData.jobstr] + ) + ) + } + } + return dataList + } + + fun get(id: Int): MatchPlanningDataData? = + transaction { + MatchPlanningData.select { MatchPlanningData.id eq id }.firstOrNull()?.let { + MatchPlanningDataData( + it[MatchPlanningData.id], + it[MatchPlanningData.serverid], + it[MatchPlanningData.channelid], + it[MatchPlanningData.matchtype], + it[MatchPlanningData.registererid], + it[MatchPlanningData.roleid], + it[MatchPlanningData.opponentName], + it[MatchPlanningData.messageid], + it[MatchPlanningData.timestamp], + it[MatchPlanningData.jobstr] + ) + } + } + + fun getFromMessageInChannelInServer(messageID: Long, channelID: Long, serverID: Long): MatchPlanningDataData? = + transaction { + MatchPlanningData.select { + MatchPlanningData.messageid eq (messageID) and ( + MatchPlanningData.serverid eq (serverID)) and ( + MatchPlanningData.channelid eq (channelID)) + }.firstOrNull()?.let { + MatchPlanningDataData( + it[MatchPlanningData.id], + it[MatchPlanningData.serverid], + it[MatchPlanningData.channelid], + it[MatchPlanningData.matchtype], + it[MatchPlanningData.registererid], + it[MatchPlanningData.roleid], + it[MatchPlanningData.opponentName], + it[MatchPlanningData.messageid], + it[MatchPlanningData.timestamp], + it[MatchPlanningData.jobstr] + ) + } + } + + fun delete(id: Int) { + transaction { + MatchPlanningData.deleteWhere { MatchPlanningData.id eq id } + } + } + + fun write(data: MatchPlanningDataData): Int = + transaction { + MatchPlanningData.insert { + it[MatchPlanningData.serverid] = data.serverID + it[MatchPlanningData.channelid] = data.channelID + it[MatchPlanningData.matchtype] = data.matchType + it[MatchPlanningData.registererid] = data.registererID + it[MatchPlanningData.roleid] = data.roleID + it[MatchPlanningData.opponentName] = data.opponentName + it[MatchPlanningData.messageid] = data.messageID + it[MatchPlanningData.timestamp] = data.timestamp + it[MatchPlanningData.jobstr] = data.jobString + } get MatchPlanningData.id + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/PlanningNotifierRolesRepository.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/PlanningNotifierRolesRepository.kt new file mode 100644 index 0000000..4059e70 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/PlanningNotifierRolesRepository.kt @@ -0,0 +1,104 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.database.repository + +import net.moonleay.lilJudd.data.database.entry.PlanningNotifierRolesData +import net.moonleay.lilJudd.data.database.tables.PlanningNotifierRoles +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.transactions.transaction + +object PlanningNotifierRolesRepository { + + fun getAll(): List { + val dataList = mutableListOf() + transaction { + for (pnr in PlanningNotifierRoles.selectAll()) { + dataList.add( + PlanningNotifierRolesData( + pnr[PlanningNotifierRoles.id], + pnr[PlanningNotifierRoles.serverid], + pnr[PlanningNotifierRoles.channelid], + pnr[PlanningNotifierRoles.hastimeroleid], + pnr[PlanningNotifierRoles.wantstobenotifiedid] + ) + ) + } + } + return dataList + } + + fun getForChannel(channelID: Long): PlanningNotifierRolesData? = + transaction { + PlanningNotifierRoles.select { + PlanningNotifierRoles.channelid eq channelID + }.firstOrNull()?.let { + PlanningNotifierRolesData( + it[PlanningNotifierRoles.id], + it[PlanningNotifierRoles.serverid], + it[PlanningNotifierRoles.channelid], + it[PlanningNotifierRoles.hastimeroleid], + it[PlanningNotifierRoles.wantstobenotifiedid] + ) + } + } + + fun getForChannelInServer(channelID: Long, serverID: Long): PlanningNotifierRolesData? = + transaction { + PlanningNotifierRoles.select { + PlanningNotifierRoles.channelid eq channelID and (PlanningNotifierRoles.serverid eq serverID) + }.firstOrNull()?.let { + PlanningNotifierRolesData( + it[PlanningNotifierRoles.id], + it[PlanningNotifierRoles.serverid], + it[PlanningNotifierRoles.channelid], + it[PlanningNotifierRoles.hastimeroleid], + it[PlanningNotifierRoles.wantstobenotifiedid] + ) + } + } + + fun existsInChannel(channelID: Long): Boolean = + transaction { + PlanningNotifierRoles.select { PlanningNotifierRoles.channelid eq channelID }.count() > 0 + } + + fun existsInChannelFromSever(channelID: Long, serverID: Long): Boolean = + transaction { + PlanningNotifierRoles.select { PlanningNotifierRoles.channelid eq channelID and (PlanningNotifierRoles.serverid eq serverID) } + .count() > 0 + } + + fun write(data: PlanningNotifierRolesData) { + transaction { + PlanningNotifierRoles.insert { + it[PlanningNotifierRoles.serverid] = data.serverID + it[PlanningNotifierRoles.channelid] = data.channelID + it[PlanningNotifierRoles.hastimeroleid] = data.hasTimeRoleID + it[PlanningNotifierRoles.wantstobenotifiedid] = data.wantsToBeNotifiedID + } get PlanningNotifierRoles.id + } + } + + fun delete(id: Int) { + transaction { + PlanningNotifierRoles.deleteWhere { PlanningNotifierRoles.id eq id } + } + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/TimePlanningChannelsRepository.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/TimePlanningChannelsRepository.kt new file mode 100644 index 0000000..f5fd171 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/TimePlanningChannelsRepository.kt @@ -0,0 +1,69 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.database.repository + +import net.moonleay.lilJudd.data.database.entry.TimePlanningChannelsData +import net.moonleay.lilJudd.data.database.tables.TimePlanningChannels +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.transactions.transaction + +object TimePlanningChannelsRepository { + + fun getAll(): List { + val dataList = mutableListOf() + transaction { + for (tp in TimePlanningChannels.selectAll()) + dataList.add( + TimePlanningChannelsData( + id = tp[TimePlanningChannels.id], + serverID = tp[TimePlanningChannels.serverid], + channelID = tp[TimePlanningChannels.channelid], + ) + ) + } + return dataList + } + + fun exists(channelID: Long, serverID: Long): Boolean = + transaction { + TimePlanningChannels.select { TimePlanningChannels.channelid eq channelID and (TimePlanningChannels.serverid eq serverID) } + .firstOrNull() != null + } + + fun delete(id: Int) { + transaction { + TimePlanningChannels.deleteWhere { TimePlanningChannels.id eq id } + } + } + + fun deleteFromChannelInServer(channelID: Long, serverID: Long) { + transaction { + TimePlanningChannels.deleteWhere { TimePlanningChannels.channelid eq channelID and (TimePlanningChannels.serverid eq serverID) } + } + } + + fun write(data: TimePlanningChannelsData): Int = + transaction { + TimePlanningChannels.insert { + it[TimePlanningChannels.serverid] = data.serverID + it[TimePlanningChannels.channelid] = data.channelID + } get TimePlanningChannels.id + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/TimePlanningMessagesRepository.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/TimePlanningMessagesRepository.kt new file mode 100644 index 0000000..780a939 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/repository/TimePlanningMessagesRepository.kt @@ -0,0 +1,76 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.database.repository + +import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData +import net.moonleay.lilJudd.data.database.tables.TimePlanningMessages +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.insert +import org.jetbrains.exposed.sql.select +import org.jetbrains.exposed.sql.transactions.transaction + +object TimePlanningMessagesRepository { + + fun write(data: TimePlanningMessagesData): Int = + transaction { + TimePlanningMessages.insert { + it[serverid] = data.serverID + it[channelid] = data.channelID + it[weekstamp] = data.weekstamp + it[messageids] = data.messageIDs + } get TimePlanningMessages.id + } + + fun getWeek(stamp: Long): List { + val dataList = mutableListOf() + transaction { + for (pnr in TimePlanningMessages.select { + TimePlanningMessages.weekstamp eq (stamp) + }) { + dataList.add( + TimePlanningMessagesData( + pnr[TimePlanningMessages.id], + pnr[TimePlanningMessages.serverid], + pnr[TimePlanningMessages.channelid], + pnr[TimePlanningMessages.weekstamp], + pnr[TimePlanningMessages.messageids] + ) + ) + } + } + return dataList + } + + fun getWeekInChannel(stamp: Long, channelID: Long): TimePlanningMessagesData? = + transaction { + TimePlanningMessages.select { + TimePlanningMessages.weekstamp eq (stamp) and (TimePlanningMessages.channelid eq channelID) + }.firstOrNull()?.let { + TimePlanningMessagesData( + it[TimePlanningMessages.id], + it[TimePlanningMessages.serverid], + it[TimePlanningMessages.channelid], + it[TimePlanningMessages.weekstamp], + it[TimePlanningMessages.messageids] + ) + } + } + + +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/tables/MatchPlanningData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/MatchPlanningData.kt similarity index 66% rename from src/main/kotlin/net/moonleay/lilJudd/data/tables/MatchPlanningData.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/database/tables/MatchPlanningData.kt index 2de3ece..391b3e8 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/tables/MatchPlanningData.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/MatchPlanningData.kt @@ -16,18 +16,19 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data.tables +package net.moonleay.lilJudd.data.database.tables -import org.jetbrains.exposed.dao.id.IntIdTable +import org.jetbrains.exposed.sql.Table -object MatchPlanningData : IntIdTable() { - var serverid = varchar("serverid", 50) - var channelid = varchar("channelid", 50) +object MatchPlanningData : Table(name = "new_matchplanning_data") { + var id = integer("id").autoIncrement() + var serverid = long("serverid") + var channelid = long("channelid") var matchtype = varchar("matchtype", 50) - var registererid = varchar("registererid", 50) - var roleid = varchar("roleid", 50) + var registererid = long("registererid") + var roleid = long("roleid") var opponentName = varchar("opponentname", 100) - var messageid = varchar("messageid", 50) - var timestamp = varchar("timestamp", 50) + var messageid = long("messageid") + var timestamp = long("timestamp") var jobstr = varchar("jobstr", 50) } diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/PlanningNotifierRoles.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/PlanningNotifierRoles.kt new file mode 100644 index 0000000..66fe906 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/PlanningNotifierRoles.kt @@ -0,0 +1,29 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.database.tables + +import org.jetbrains.exposed.sql.Table + +object PlanningNotifierRoles : Table(name = "new_planningnotifier_roles") { + var id = integer("id").autoIncrement() + var serverid = long("serverid") + var channelid = long("channelid") + var hastimeroleid = long("hastimeroleid") + var wantstobenotifiedid = long("wantstobenotifiedid") +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/TimePlanningChannels.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/TimePlanningChannels.kt new file mode 100644 index 0000000..d3b31e3 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/TimePlanningChannels.kt @@ -0,0 +1,28 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.data.database.tables + +import org.jetbrains.exposed.sql.Table + + +object TimePlanningChannels : Table(name = "new_timeplanning_channels") { + var id = integer("id").autoIncrement() + var serverid = long("serverid") + val channelid = long("channelid") +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/tables/TimePlanningMessages.kt b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/TimePlanningMessages.kt similarity index 70% rename from src/main/kotlin/net/moonleay/lilJudd/data/tables/TimePlanningMessages.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/database/tables/TimePlanningMessages.kt index 7498edb..dd48838 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/tables/TimePlanningMessages.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/database/tables/TimePlanningMessages.kt @@ -16,13 +16,14 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data.tables +package net.moonleay.lilJudd.data.database.tables -import org.jetbrains.exposed.dao.id.IntIdTable +import org.jetbrains.exposed.sql.Table -object TimePlanningMessages : IntIdTable() { - var serverid = varchar("serverid", 50) - var channelid = varchar("channelid", 50) - var weekstamp = varchar("weekstamp", 50) +object TimePlanningMessages : Table(name = "new_timeplanning_messages") { + var id = integer("id").autoIncrement() + var serverid = long("serverid") + var channelid = long("channelid") + var weekstamp = long("weekstamp") var messageids = varchar("messageids", 200) } diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt index 48f68e9..e09786c 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt @@ -25,11 +25,11 @@ import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.utils.hasPermission -import dev.kord.common.Color import dev.kord.common.entity.Permission import net.moonleay.lilJudd.extensions.component.EnableOrDisable import net.moonleay.lilJudd.features.component.FeatureEnum import net.moonleay.lilJudd.features.component.FeatureManager +import net.moonleay.lilJudd.util.EmbedColor import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.MessageUtil @@ -51,7 +51,7 @@ class FeatureManageExtension : Extension() { this.respond { embeds.add( MessageUtil.getEmbed( - Color(0xE0311A), + EmbedColor.ERROR, "403: Forbidden", "You cannot edit features, as you don't have the Administrator permission.", u.asUser().username + "#" + u.asUser().discriminator @@ -60,8 +60,8 @@ class FeatureManageExtension : Extension() { } return@action } - val gID = this.guild!!.id.toString() - val cID = this.arguments.channel.id.toString() + val gID = this.guild!!.id.value.toLong() + val cID = this.arguments.channel.id.value.toLong() val channel = this.arguments.channel val args = this.arguments Logger.out("${args.feature.readableName} ${args.setStatus.readableName} ${channel.data.name.value}") @@ -70,7 +70,7 @@ class FeatureManageExtension : Extension() { this.respond { this.embeds.add( MessageUtil.getEmbed( - Color(0xE0311A), + EmbedColor.ERROR, "404: Not Found", "The feature you are trying to edit does not exist.", u.asUser().username + "#" + u.asUser().discriminator diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/VersionExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/InfoExtension.kt similarity index 82% rename from src/main/kotlin/net/moonleay/lilJudd/extensions/VersionExtension.kt rename to src/main/kotlin/net/moonleay/lilJudd/extensions/InfoExtension.kt index c116c02..6445faf 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/VersionExtension.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/extensions/InfoExtension.kt @@ -20,25 +20,26 @@ package net.moonleay.lilJudd.extensions import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand -import dev.kord.common.Color -import net.moonleay.botendo.build.BuildConstants +import net.moonleay.lilJudd.util.EmbedColor import net.moonleay.lilJudd.util.MessageUtil +import net.moonleay.liljudd.build.BuildConstants -class VersionExtension : Extension() { - override val name = "version" +class InfoExtension : Extension() { + override val name = "info" override suspend fun setup() { publicSlashCommand { - name = "version" + name = "info" description = "Show infos about the bot" this.action { MessageUtil.sendEmbedForPublicSlashCommand( this, - Color(0x52E01A), + EmbedColor.INFO, "Lil' Judd", "Lil' Judd ***v." + BuildConstants.version + "***\n" + "Kord-Extensions ***v." + BuildConstants.kordVersion + "***\n" + "Coroutines ***v." + BuildConstants.coroutinesVersion + "***\n" + - "Krontab ***v." + BuildConstants.krontabVersion + "***" + "Krontab ***v." + BuildConstants.krontabVersion + "***\n\n" + + "Splatoon 3 api data provided by splatoon3.ink" ) } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/MatchExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/MatchExtension.kt index be28081..9f2674d 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/MatchExtension.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/extensions/MatchExtension.kt @@ -25,20 +25,18 @@ import com.kotlindiscord.kord.extensions.commands.converters.impl.string import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.types.respond -import dev.kord.common.Color import dev.kord.core.behavior.channel.createMessage import dev.kord.core.behavior.createRole import dev.kord.rest.builder.message.create.actionRow -import net.moonleay.lilJudd.data.tables.MatchPlanningData +import net.moonleay.lilJudd.data.database.entry.MatchPlanningDataData +import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository import net.moonleay.lilJudd.extensions.component.MatchTypes import net.moonleay.lilJudd.jobs.MatchJob import net.moonleay.lilJudd.jobs.component.JobManager +import net.moonleay.lilJudd.util.EmbedColor import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.MessageUtil import net.moonleay.lilJudd.util.TimeUtil -import org.jetbrains.exposed.dao.id.EntityID -import org.jetbrains.exposed.sql.insert -import org.jetbrains.exposed.sql.transactions.transaction class MatchExtension : Extension() { @@ -54,19 +52,20 @@ class MatchExtension : Extension() { this.action { val args = this.arguments val m = this.member!! - val gID = this.guild!!.id.value.toString() - val cID = this.channel.id.value.toString() + val gID = this.guild!!.id.value + val cID = this.channel.id.value val opponent = args.opponent ?: "?" val msg = this.respond { this.embeds.add( MessageUtil.getEmbedWithTable( - Color(0X4C4645), + EmbedColor.INFO, args.matchType.readableName, "***Vs. $opponent***\n" + "At ${args.timeStamp}\n" + "Registered by ${m.mention}", mapOf( "Signed up" to listOf(), + "Unavailable" to listOf(), ) ) ) @@ -89,7 +88,7 @@ class MatchExtension : Extension() { this.channel.createMessage { this.embeds.add( MessageUtil.getEmbed( - Color(0xE0311A), + EmbedColor.ERROR, "500: Internal Error", "Could not find created role.\n" + "It seems, that said role could not be created.", @@ -99,28 +98,28 @@ class MatchExtension : Extension() { } return@action } - lateinit var tableID: EntityID - transaction { - tableID = MatchPlanningData.insert { - it[MatchPlanningData.serverid] = gID - it[MatchPlanningData.channelid] = cID - it[MatchPlanningData.messageid] = msg.id.value.toString() - it[MatchPlanningData.matchtype] = args.matchType.readableName - it[MatchPlanningData.roleid] = role.id.value.toString() - it[MatchPlanningData.registererid] = m.id.value.toString() - it[MatchPlanningData.opponentName] = opponent - it[MatchPlanningData.timestamp] = (zdt.toEpochSecond() * 1000).toString() - it[MatchPlanningData.jobstr] = jobString - } get MatchPlanningData.id - } - if (tableID == null) { + val tID = MatchPlanningDataRepository.write( + MatchPlanningDataData( + 0, + gID.toLong(), + cID.toLong(), + args.matchType.readableName, + m.id.value.toLong(), + role.id.value.toLong(), + opponent, + msg.id.value.toLong(), + (zdt.toEpochSecond() * 1000), + jobString + ) + ) + if (tID == null || tID <= 0) { return@action // Not saved to db } JobManager.addJob( MatchJob( jobString, - tableID.value, - "${args.matchType.readableName}_Vs_${opponent}_[${tableID.value}]-${gID}_${cID}" + tID, + "${args.matchType.readableName}_Vs_${opponent}_[${tID}]-${gID}_${cID}", ) ) } diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt index 2a56745..781de2c 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt @@ -22,18 +22,13 @@ import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.utils.hasPermission -import dev.kord.common.Color import dev.kord.common.entity.Permission import dev.kord.core.behavior.channel.createMessage import dev.kord.rest.builder.message.create.actionRow import kotlinx.coroutines.delay -import net.moonleay.lilJudd.data.tables.TimePlanningMessages -import net.moonleay.lilJudd.util.EmbedUtil -import net.moonleay.lilJudd.util.Logger -import net.moonleay.lilJudd.util.MessageUtil -import net.moonleay.lilJudd.util.TimeUtil -import org.jetbrains.exposed.sql.insert -import org.jetbrains.exposed.sql.transactions.transaction +import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData +import net.moonleay.lilJudd.data.database.repository.TimePlanningMessagesRepository +import net.moonleay.lilJudd.util.* import java.time.ZoneId import java.time.ZonedDateTime @@ -47,13 +42,13 @@ class SendPlannerExtension : Extension() { override suspend fun setup() { publicSlashCommand() { name = "sendplanner" - description = "Send the planner for the current and x next weeks" + description = "Send the planner for the current week" this.action { if (!this.member!!.asMember(this.guild!!.id) .hasPermission(Permission.Administrator) ) { val res = this.respond { - this.content = "no." + this.content = "You need to be an administrator to use this command." } res.delete() return@action @@ -71,7 +66,7 @@ class SendPlannerExtension : Extension() { c.createMessage { this.embeds.add( MessageUtil.getEmbed( - Color(0X4C4645), + EmbedColor.INFO, "Time Planning Feature", "Do you have time on the following Days?", "Automated Message" @@ -83,7 +78,7 @@ class SendPlannerExtension : Extension() { val msg = c.createMessage { this.embeds.add( MessageUtil.getEmbedWithTable( - Color(0X4C4645), + EmbedColor.INFO, "", "${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday", mapOf( @@ -105,14 +100,15 @@ class SendPlannerExtension : Extension() { } // Save the message ids - transaction { - TimePlanningMessages.insert { - it[serverid] = c.data.guildId.value.toString() - it[channelid] = c.id.value.toString() - it[weekstamp] = (TimeUtil.getWeekStamp().toEpochSecond() * 1000).toString() - it[messageids] = msgStr - } get TimePlanningMessages.id - } + TimePlanningMessagesRepository.write( + TimePlanningMessagesData( + -1, + c.data.guildId.value?.value!!.toLong(), + c.id.value.toLong(), + (TimeUtil.getWeekStamp().toEpochSecond()), + msgStr + ) + ) Logger.out("Finished with ${c.data.guildId.value}") } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/TestExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/TestExtension.kt deleted file mode 100644 index 90cda76..0000000 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/TestExtension.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * lilJudd - * Copyright (C) 2023 moonleay - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package net.moonleay.lilJudd.extensions - -import com.kotlindiscord.kord.extensions.extensions.Extension -import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand -import com.kotlindiscord.kord.extensions.types.respond -import dev.kord.common.Color -import dev.kord.rest.builder.message.create.actionRow -import net.moonleay.lilJudd.util.EmbedUtil -import net.moonleay.lilJudd.util.MessageUtil - -/* This extension has no proper use. - It is used in testing to test stuff, without having to wait for certain events to trigger. */ -class TestExtension : Extension() { - override val name = "test" - override val allowApplicationCommandInDMs: Boolean - get() = false - - override suspend fun setup() { - publicSlashCommand { - name = "test" - description = "Test game" - this.action { - this.respond { - this.embeds.add( - MessageUtil.getEmbedWithTable( - Color(0X4C4645), - "", - "MONDAY, 22.05.2023", - mapOf( - "Is available" to listOf(), - "May be available" to listOf(), - "Is not available" to listOf() - ) - ) - ) - - this.actionRow { - this.components.addAll(EmbedUtil.getTimePlannerButtons().components) - } - } - } - } - } -} diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/UpdateRolesExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/UpdateRolesExtension.kt index 109e3c7..be6ba80 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/UpdateRolesExtension.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/extensions/UpdateRolesExtension.kt @@ -23,16 +23,16 @@ import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.utils.hasPermission import dev.kord.common.entity.Permission -import dev.kord.gateway.PrivilegedIntent import net.moonleay.lilJudd.features.AvailabilityManager +import net.moonleay.lilJudd.util.EmbedColor import net.moonleay.lilJudd.util.Logger +import net.moonleay.lilJudd.util.MessageUtil class UpdateRolesExtension : Extension() { override val name = "updateroles" override val allowApplicationCommandInDMs: Boolean get() = false - @OptIn(PrivilegedIntent::class) override suspend fun setup() { publicSlashCommand() { name = "updateroles" @@ -41,21 +41,34 @@ class UpdateRolesExtension : Extension() { if (!this.member!!.asMember(this.guild!!.id) .hasPermission(Permission.Administrator) ) { - val res = this.respond { - this.content = "no." + this.respond { + this.embeds.add( + MessageUtil.getEmbed( + EmbedColor.ERROR, + "403: Forbidden", + "You need to be an administrator to use this command.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) } - res.delete() return@action } - val res = this.respond { - this.content = "OK." + this.respond { + this.embeds.add( + MessageUtil.getEmbed( + EmbedColor.SUCCESS, + "200: Success", + "Updating roles.\n" + + "This may take a while, please be patient.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) } - // -- below here is the code of the cronjob -- Logger.out("Starting to update roles...") - AvailabilityManager.runThread() + AvailabilityManager.updateInChannel(this.channel.id) } } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/features/AvailabilityManager.kt b/src/main/kotlin/net/moonleay/lilJudd/features/AvailabilityManager.kt index 1359f50..cc49d1c 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/features/AvailabilityManager.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/features/AvailabilityManager.kt @@ -18,9 +18,9 @@ package net.moonleay.lilJudd.features +import com.kotlindiscord.kord.extensions.utils.isNullOrBot import dev.inmo.krontab.buildSchedule import dev.inmo.krontab.doInfinity -import dev.kord.common.Color import dev.kord.common.entity.Snowflake import dev.kord.core.behavior.UserBehavior import dev.kord.core.behavior.createRole @@ -30,129 +30,133 @@ import dev.kord.core.entity.channel.MessageChannel import dev.kord.gateway.PrivilegedIntent import dev.kord.rest.builder.message.EmbedBuilder import net.moonleay.lilJudd.Bot -import net.moonleay.lilJudd.data.entry.PlanningNotifierRolesData -import net.moonleay.lilJudd.data.entry.TimePlanningMessagesData -import net.moonleay.lilJudd.data.tables.PlanningNotifierRoles -import net.moonleay.lilJudd.data.tables.TimePlanningMessages +import net.moonleay.lilJudd.data.database.entry.PlanningNotifierRolesData +import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData +import net.moonleay.lilJudd.data.database.repository.PlanningNotifierRolesRepository +import net.moonleay.lilJudd.data.database.repository.TimePlanningMessagesRepository import net.moonleay.lilJudd.extensions.FeatureManageExtension import net.moonleay.lilJudd.features.component.FeatureEnum import net.moonleay.lilJudd.features.component.IFeature -import net.moonleay.lilJudd.util.EmbedUtil -import net.moonleay.lilJudd.util.Logger -import net.moonleay.lilJudd.util.MessageUtil -import net.moonleay.lilJudd.util.TimeUtil -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.jetbrains.exposed.sql.transactions.transaction +import net.moonleay.lilJudd.util.* import java.time.ZonedDateTime object AvailabilityManager : IFeature { // This runs during the cronjob. - @OptIn(PrivilegedIntent::class) suspend fun runThread() { Logger.out("Starting to update roles...") // ChannelID, Data - val messageMap = mutableMapOf() - // ChannelID, Data - val roleMap = mutableMapOf() - - transaction { - for (pnr in TimePlanningMessages.select { - TimePlanningMessages.weekstamp eq (TimeUtil.getWeekStamp().toEpochSecond() * 1000).toString() - }) { - messageMap[Snowflake(pnr[TimePlanningMessages.channelid])] = - TimePlanningMessagesData( - pnr[TimePlanningMessages.serverid], - pnr[TimePlanningMessages.channelid], - pnr[TimePlanningMessages.weekstamp], - pnr[TimePlanningMessages.messageids] - ) - } - for (pnr in PlanningNotifierRoles.selectAll()) { - roleMap[pnr[PlanningNotifierRoles.channelid]] = - PlanningNotifierRolesData( - pnr[PlanningNotifierRoles.serverid], - pnr[PlanningNotifierRoles.channelid], - pnr[PlanningNotifierRoles.hastimeroleid], - pnr[PlanningNotifierRoles.wantstobenotifiedid] - ) - } + val messages = TimePlanningMessagesRepository.getWeek(TimeUtil.getWeekStamp().toEpochSecond()) + .associateBy { it.channelID } + val targetedRoles = PlanningNotifierRolesRepository.getAll().associateBy { it.channelID } + if (targetedRoles.isEmpty()) { + Logger.out("No saved roles. Canceling.") + return } - val weekday = ZonedDateTime.now().dayOfWeek // The current week day - val weekStamp = TimeUtil.getWeekStamp().toEpochSecond() * 1000 // The current week time stamp - Logger.out("It is week ${weekStamp} and day ${weekday}/${TimeUtil.getDayOfMonthInt(weekday)} of the week.") - for (snf in messageMap.keys) { // snf = Snowflake - val data = messageMap[snf]!! // this is the data of the table - if (Bot.bot.kordRef.getChannel(Snowflake(data.channelid)) == null) - continue // This channel does not exist anymore. - val c = - Bot.bot.kordRef.getChannelOf(Snowflake(data.channelid))!! // Get the channel as MessageChannel - if (roleMap.isEmpty()) { - Logger.out("No saved roles. Canceling.") - return + for (id in messages.keys) { + val snf = Snowflake(id) // snf = Snowflake + val data = messages[id]!! // this is the data of the table + if (Bot.bot.kordRef.getChannel(Snowflake(data.channelID)) == null) { + // This channel does not exist anymore. + Logger.out("Warning: Channel ${data.channelID} does not exist anymore. Skipping.") + continue } - val roleData = roleMap[data.channelid] // Get the role data + val roleData = targetedRoles[data.channelID] // Get the role data if (roleData == null) { - Logger.out("Role for this channel does not exist") - return - } - val g = Bot.bot.kordRef.getGuildOrThrow(Snowflake(data.serverid)) - // Get all members with the role - val mce = g.requestMembers { - this.requestAllMembers() - } - mce.collect { memberchunkevent -> - memberchunkevent.members.forEach { - Logger.out("Checking member ${it.id.value}") - if (it.roleIds.contains(Snowflake(roleData.hastimeroleid))) - it.removeRole(Snowflake(roleData.hastimeroleid)) - } - } - - Logger.out("Got through all members") - // This stores the ids of the messages. - // The format is weekdaNR:ID - // The last entry (nr 8) is empty, so we can ignore it - val messageIdSplit = data.messageids.split(";").subList(0, 7) - for (mid in messageIdSplit) { - Logger.out("Checking id $mid") - if (!mid.startsWith((TimeUtil.getDayOfMonthInt(weekday) - 1).toString(), true)) - continue // This is not the right message, check the next one - val idFiltered = mid.split(":")[1] // This is the target message id - val message = c.getMessageOrNull(Snowflake(idFiltered)) // Get the message from the channel - if (message == null) { - Logger.out("Could not find message.") - break // This message does not exist anymore. Nothing we can do about that. - } - if (message.data.embeds.isEmpty()) { - Logger.out("There are no embeds.") - break // There are no embeds or there are not enough embeds - } - val targets = EmbedUtil.getAllUsersInTheFirstXTables(2, message.embeds[0]) - for (tid in targets) { - Logger.out("Checking id $tid") - if (Bot.bot.kordRef.getGuildOrNull(Snowflake(data.serverid))!! - .getMemberOrNull(Snowflake(tid)) == null - ) - continue // This member does not exist anymore. - val member = Bot.bot.kordRef.getGuildOrThrow(Snowflake(data.serverid)) - .getMember(Snowflake(tid)) // Get the member - if (member.roleIds.contains(Snowflake(roleData.hastimeroleid))) - continue // This member already has the role - member.addRole(Snowflake(roleData.hastimeroleid)) // Add the role - Logger.out("Added role to ${member.username}") - } - Logger.out("Done with message. Moving on...") - // We found the right message. We don't need to check the others. - break + Logger.out("Role for channel ${data.channelID} does not exist") + continue // this took way to long to find out that this was the issue } + this.updateInChannel(snf, data, roleData) } Logger.out("Done! Until tomorrow! <3 ") } + suspend fun updateInChannel(snf: Snowflake) { + val stamp = TimeUtil.getWeekStamp().toEpochSecond() + Logger.out("Weekstamp: $stamp") + val messageData = TimePlanningMessagesRepository.getWeekInChannel( + stamp, + snf.value.toLong() + ) + if (messageData == null) { + Logger.out("Could not find data for channel ${snf.value}") + return + } + val roleData = PlanningNotifierRolesRepository.getForChannel(snf.value.toLong()) + if (roleData == null) { + Logger.out("Role for channel ${messageData.channelID} does not exist") + return // this took way to long to find out that this was the issue + } + updateInChannel(snf, messageData, roleData) + } + + @OptIn(PrivilegedIntent::class) + suspend fun updateInChannel(snf: Snowflake, tpmd: TimePlanningMessagesData, pnrd: PlanningNotifierRolesData) { + if (Bot.bot.kordRef.getChannel(snf) == null) + return // This channel does not exist anymore. + val c = Bot.bot.kordRef.getChannelOf(snf)!! // Get the channel as MessageChannel + val weekday = ZonedDateTime.now().dayOfWeek // The current week day + val weekStamp = TimeUtil.getWeekStamp().toEpochSecond() // The current week time stamp + Logger.out("It is week ${weekStamp} and day ${weekday}/${TimeUtil.getDayOfMonthInt(weekday)} of the week.") + val g = Bot.bot.kordRef.getGuild(Snowflake(tpmd.serverID)) + // Get all members with the role + val mce = g.requestMembers { + this.requestAllMembers() + } + mce.collect { memberchunkevent -> + memberchunkevent.members.forEach { + if (!it.isNullOrBot()) { // Check if the member is a bot + Logger.out("Checking member ${it.id.value} (${it.username})") + if (it.roleIds.contains(Snowflake(pnrd.hasTimeRoleID))) { + it.removeRole(Snowflake(pnrd.hasTimeRoleID)) + Logger.out("Removed role from ${it.username}") // Removed the role + } + } + // I cant use continue here, because it does not work with .forEach + } + } + + Logger.out("Got through all members") + // This stores the ids of the messages. + // The format is weekdaNR:ID + // The last entry (nr 8) is empty, so we can ignore it + val messageIdSplit = tpmd.messageIDs.split(";").subList(0, 7) + for (mid in messageIdSplit) { + Logger.out("Checking id $mid") + if (!mid.startsWith((TimeUtil.getDayOfMonthInt(weekday) - 1).toString(), true)) + continue// This is not the right message, check the next one + val idFiltered = mid.split(":")[1] // This is the target message id + val message = c.getMessageOrNull(Snowflake(idFiltered)) // Get the message from the channel + if (message == null) { + Logger.out("Could not find message.") + return // This message does not exist anymore. Nothing we can do about that. + } + if (message.data.embeds.isEmpty()) { + Logger.out("There are no embeds.") + return // There are no embeds or there are not enough embeds + } + val targets = EmbedUtil.getAllUsersInTheFirstXTables(2, message.embeds[0]) + for (tid in targets) { + Logger.out("Checking id $tid") + if (Bot.bot.kordRef.getGuildOrNull(Snowflake(tpmd.serverID))!! + .getMemberOrNull(Snowflake(tid)) == null + ) + continue// This member does not exist anymore. + val member = Bot.bot.kordRef.getGuild(Snowflake(tpmd.serverID)) + .getMember(Snowflake(tid)) // Get the member + if (member.roleIds.contains(Snowflake(pnrd.hasTimeRoleID))) + continue // This member already has the role + member.addRole(Snowflake(pnrd.hasTimeRoleID)) // Add the role + Logger.out("Added role to ${member.username}") + } + Logger.out("Done with message. Moving on...") + // We found the right message. We don't need to check the others. + break + } + } + override val feat: FeatureEnum get() = FeatureEnum.PLANNINGROLES @@ -167,44 +171,40 @@ object AvailabilityManager : IFeature { override suspend fun enable( u: UserBehavior, - gID: String, - cID: String, + gID: Long, + cID: Long, ch: Channel, args: FeatureManageExtension.FeatureManagerArgs ): EmbedBuilder { - var alreadyExists = false + var alreadyExists = PlanningNotifierRolesRepository.existsInChannel(cID) // Check if the channel and guild already exist in the db - transaction { - alreadyExists = PlanningNotifierRoles.select { - (PlanningNotifierRoles.serverid eq gID) and (PlanningNotifierRoles.channelid eq cID) - }.count() > 0 - } if (!alreadyExists) { // Create the roles in Discord - val hasTimeRole = Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)).createRole { + val hasTimeRole = Bot.bot.kordRef.getGuild(Snowflake(gID)).createRole { this.name = "available [${ch.data.name.value}]" this.mentionable = true } - val htr = hasTimeRole.id.toString() + val htr = hasTimeRole.id.value.toLong() - val wantsNotifsRole = Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)).createRole { + val wantsNotifsRole = Bot.bot.kordRef.getGuild(Snowflake(gID)).createRole { this.name = "notifications [${ch.data.name.value}]" this.mentionable = true } - val wnr = wantsNotifsRole.id.toString() + val wnr = wantsNotifsRole.id.value.toLong() // Save the role ids to db - transaction { - PlanningNotifierRoles.insert { - it[PlanningNotifierRoles.serverid] = gID - it[PlanningNotifierRoles.channelid] = cID - it[PlanningNotifierRoles.hastimeroleid] = htr - it[PlanningNotifierRoles.wantstobenotifiedid] = wnr - } get PlanningNotifierRoles.id - } + PlanningNotifierRolesRepository.write( + PlanningNotifierRolesData( + id = -1, + serverID = gID, + channelID = cID, + hasTimeRoleID = htr, + wantsToBeNotifiedID = wnr + ) + ) return MessageUtil.getEmbed( - Color(0x52E01A), + EmbedColor.SUCCESS, "200: Success", "The feature was enabled in channel ${args.channel.data.name.value} with roles ${hasTimeRole.mention} & ${wantsNotifsRole.mention}.", u.asUser().username + "#" + u.asUser().discriminator @@ -213,7 +213,7 @@ object AvailabilityManager : IFeature { // They exist, do not add them return MessageUtil.getEmbed( - Color(0xE0311A), + EmbedColor.ERROR, "403: Forbidden", "The feature is already enabled in this channel.", u.asUser().username + "#" + u.asUser().discriminator @@ -222,43 +222,24 @@ object AvailabilityManager : IFeature { override suspend fun disable( u: UserBehavior, - gID: String, - cID: String, + gID: Long, + cID: Long, ch: Channel, args: FeatureManageExtension.FeatureManagerArgs ): EmbedBuilder { // Check if entry exists in db - var alreadyExists = false - transaction { - alreadyExists = PlanningNotifierRoles.select { - (PlanningNotifierRoles.serverid eq gID) and (PlanningNotifierRoles.channelid eq cID) - }.count() > 0 - } - if (alreadyExists) { - var matchingEntries: List = mutableListOf() - transaction { - matchingEntries = PlanningNotifierRoles.select { - (PlanningNotifierRoles.serverid eq gID) and - (PlanningNotifierRoles.channelid eq cID) - }.toList() - } + if (PlanningNotifierRolesRepository.existsInChannelFromSever(cID, gID)) { + val entry = PlanningNotifierRolesRepository.getForChannelInServer(cID, gID)!! // delete all entries for this guild and channel combo - for (e in matchingEntries) { - Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)) - .getRoleOrNull(Snowflake(e[PlanningNotifierRoles.hastimeroleid]))?.delete() - Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)) - .getRoleOrNull(Snowflake(e[PlanningNotifierRoles.wantstobenotifiedid])) - ?.delete() - } + Bot.bot.kordRef.getGuild(Snowflake(gID)) + .getRoleOrNull(Snowflake(entry.hasTimeRoleID))?.delete() + Bot.bot.kordRef.getGuild(Snowflake(gID)) + .getRoleOrNull(Snowflake(entry.wantsToBeNotifiedID))?.delete() // delete all found entries - transaction { - matchingEntries.forEach { entry -> - PlanningNotifierRoles.deleteWhere { id eq entry[id] } - } - } + PlanningNotifierRolesRepository.delete(entry.id) return MessageUtil.getEmbed( - Color(0x52E019), + EmbedColor.SUCCESS, "200: Success", "The feature was disabled.", u.asUser().username + "#" + u.asUser().discriminator @@ -266,7 +247,7 @@ object AvailabilityManager : IFeature { } // not in db, do nothing return MessageUtil.getEmbed( - Color(0xE0311A), + EmbedColor.ERROR, "403: Forbidden", "The feature is already disabled in this channel.", u.asUser().username + "#" + u.asUser().discriminator diff --git a/src/main/kotlin/net/moonleay/lilJudd/features/MatchManager.kt b/src/main/kotlin/net/moonleay/lilJudd/features/MatchManager.kt index a92ad6a..129fdc0 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/features/MatchManager.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/features/MatchManager.kt @@ -20,47 +20,23 @@ package net.moonleay.lilJudd.features import dev.kord.common.entity.Snowflake import net.moonleay.lilJudd.Bot -import net.moonleay.lilJudd.data.entry.MatchPlanningDataData -import net.moonleay.lilJudd.data.tables.MatchPlanningData +import net.moonleay.lilJudd.data.database.entry.MatchPlanningDataData +import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository import net.moonleay.lilJudd.jobs.MatchJob import net.moonleay.lilJudd.jobs.component.JobManager import net.moonleay.lilJudd.util.Logger -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.jetbrains.exposed.sql.deleteWhere -import org.jetbrains.exposed.sql.selectAll -import org.jetbrains.exposed.sql.transactions.transaction object MatchManager { suspend fun update() { Logger.out("Updating match roles...") - val dataList = mutableListOf() - transaction { - MatchPlanningData.selectAll().forEach { - dataList.add( - MatchPlanningDataData( - it[MatchPlanningData.id].value, - it[MatchPlanningData.serverid], - it[MatchPlanningData.channelid], - it[MatchPlanningData.matchtype], - it[MatchPlanningData.registererid], - it[MatchPlanningData.roleid], - it[MatchPlanningData.opponentName], - it[MatchPlanningData.messageid], - it[MatchPlanningData.timestamp], - it[MatchPlanningData.jobstr] - ) - ) - } - } + val dataList = MatchPlanningDataRepository.getAll() for (data in dataList) { Logger.out("Checking match role ${data.id}...") - if (data.timestamp.toLong() < System.currentTimeMillis()) { + if (data.timestamp < System.currentTimeMillis()) { Logger.out("Match role ${data.id} is expired, removing...") - this.removeRoleFromGuild(data.serverid, data.roleid) - transaction { - MatchPlanningData.deleteWhere { MatchPlanningData.messageid eq data.messageid } - } + this.removeRoleFromGuild(data.serverID, data.roleID) + MatchPlanningDataRepository.delete(data.id) continue } this.registerJob(data) @@ -71,17 +47,17 @@ object MatchManager { private fun registerJob(data: MatchPlanningDataData) { JobManager.addJob( MatchJob( - data.jobstr, + data.jobString, data.id, - "fromdb-${data.matchtype}_Vs_${data.opponentname}_[${data.id}]-${data.serverid}_${data.channelid}" + "fromdb-${data.matchType}_Vs_${data.opponentName}_[${data.id}]-${data.serverID}_${data.channelID}" ) ) Logger.out("Registered job for match ${data.id}...") } - private suspend fun removeRoleFromGuild(gid: String, rid: String): Boolean { - val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(gid.toLong())) ?: return false - val role = guild.getRoleOrNull(Snowflake(rid.toLong())) ?: return false + private suspend fun removeRoleFromGuild(gid: Long, rid: Long): Boolean { + val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(gid)) ?: return false + val role = guild.getRoleOrNull(Snowflake(rid)) ?: return false role.delete() return true } diff --git a/src/main/kotlin/net/moonleay/lilJudd/features/TimeManager.kt b/src/main/kotlin/net/moonleay/lilJudd/features/TimeManager.kt index 0ac7b1b..ec073ac 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/features/TimeManager.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/features/TimeManager.kt @@ -20,7 +20,6 @@ package net.moonleay.lilJudd.features import dev.inmo.krontab.buildSchedule import dev.inmo.krontab.doInfinity -import dev.kord.common.Color import dev.kord.common.entity.Snowflake import dev.kord.core.behavior.UserBehavior import dev.kord.core.behavior.channel.createMessage @@ -30,20 +29,18 @@ import dev.kord.rest.builder.message.EmbedBuilder import dev.kord.rest.builder.message.create.actionRow import kotlinx.coroutines.delay import net.moonleay.lilJudd.Bot -import net.moonleay.lilJudd.data.entry.PlanningNotifierRolesData -import net.moonleay.lilJudd.data.tables.PlanningNotifierRoles -import net.moonleay.lilJudd.data.tables.TimePlanningChannels -import net.moonleay.lilJudd.data.tables.TimePlanningMessages +import net.moonleay.lilJudd.data.database.entry.TimePlanningChannelsData +import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData +import net.moonleay.lilJudd.data.database.repository.PlanningNotifierRolesRepository +import net.moonleay.lilJudd.data.database.repository.TimePlanningChannelsRepository +import net.moonleay.lilJudd.data.database.repository.TimePlanningMessagesRepository import net.moonleay.lilJudd.extensions.FeatureManageExtension import net.moonleay.lilJudd.features.component.FeatureEnum import net.moonleay.lilJudd.features.component.IFeature +import net.moonleay.lilJudd.util.EmbedColor import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.MessageUtil -import net.moonleay.lilJudd.util.TimeUtil -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.jetbrains.exposed.sql.transactions.transaction import java.time.ZoneId import java.time.ZonedDateTime @@ -64,43 +61,26 @@ object TimeManager : IFeature { private suspend fun runThread() { Logger.out("Starting to notify...") + // ChannelID -> Data + val targetedChannels = TimePlanningChannelsRepository.getAll().associateBy { it.channelID } + val targetedRoles = PlanningNotifierRolesRepository.getAll().associateBy { it.channelID } - // ChannelID, ServerID - val channelList = mutableMapOf() - // ChannelID, Data - val roleMap = mutableMapOf() + lateinit var msgStr: String - var msgStr = "" - - transaction { - for (tp in TimePlanningChannels.selectAll()) { - channelList[Snowflake(tp[TimePlanningChannels.channelid])] = - Snowflake(tp[TimePlanningChannels.serverid]) - Logger.out("Have to notify channel with ID ${tp[TimePlanningChannels.channelid]}.") - } - - for (pnr in PlanningNotifierRoles.selectAll()) { - roleMap[Snowflake(pnr[PlanningNotifierRoles.channelid])] = PlanningNotifierRolesData( - pnr[PlanningNotifierRoles.serverid], - pnr[PlanningNotifierRoles.channelid], - pnr[PlanningNotifierRoles.hastimeroleid], - pnr[PlanningNotifierRoles.wantstobenotifiedid] - ) - Logger.out("Have to ping roles: ${pnr[PlanningNotifierRoles.wantstobenotifiedid]}}") - } - } - Logger.out("${channelList.count()} Channels to notify with ${roleMap.count()} Roles to ping!") - for (ch in channelList.keys) { + Logger.out("${targetedChannels.count()} Channels to notify with ${targetedRoles.count()} Roles to ping!") + for (ch2 in targetedChannels.keys) { + val ch = Snowflake(ch2) if (Bot.bot.kordRef.getChannel(ch) == null) continue // TODO: Check if the channel is valid in another shard val c = Bot.bot.kordRef.getChannelOf(ch)!! - if (roleMap != null && roleMap.keys.contains(ch) && roleMap[ch] != null) { + msgStr = "" + if (targetedRoles != null && targetedRoles.keys.contains(ch2) && targetedRoles[ch2] != null) { c.createMessage { this.content = - "The weekly planning starts now <@&${Snowflake(roleMap[ch]?.wantstobenotifid!!)}>" + "The weekly planning starts now <@&${Snowflake(targetedRoles[ch2]?.wantsToBeNotifiedID!!)}>" this.embeds.add( MessageUtil.getEmbed( - Color(0X4C4645), + EmbedColor.INFO, "Time Planning Feature", "Do you have time on the following Days?", "Automated Message" @@ -111,7 +91,7 @@ object TimeManager : IFeature { c.createMessage { this.embeds.add( MessageUtil.getEmbed( - Color(0X4C4645), + EmbedColor.INFO, "Time Planning Feature", "Do you have time on the following Days?", "Automated Message" @@ -125,7 +105,7 @@ object TimeManager : IFeature { val msg = c.createMessage { this.embeds.add( MessageUtil.getEmbedWithTable( - Color(0X4C4645), + EmbedColor.INFO, "", "${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday", mapOf( @@ -148,14 +128,15 @@ object TimeManager : IFeature { } // Save the message ids - transaction { - TimePlanningMessages.insert { - it[TimePlanningMessages.serverid] = c.data.guildId.value.toString() - it[TimePlanningMessages.channelid] = c.id.value.toString() - it[TimePlanningMessages.weekstamp] = TimeUtil.getWeekStamp().toOffsetDateTime().toString() - it[TimePlanningMessages.messageids] = msgStr - } get TimePlanningMessages.id - } + TimePlanningMessagesRepository.write( + TimePlanningMessagesData( + id = -1, + serverID = c.data.guildId.value?.value!!.toLong(), + channelID = c.data.id.value.toLong(), + weekstamp = then.minusDays(7).toEpochSecond(), + messageIDs = msgStr + ) + ) Logger.out("Finished with ${c.data.guildId.value}") } Logger.out("Done! Until next Monday! <3 ") @@ -163,34 +144,22 @@ object TimeManager : IFeature { override suspend fun enable( u: UserBehavior, - gID: String, - cID: String, + gID: Long, + cID: Long, ch: Channel, args: FeatureManageExtension.FeatureManagerArgs ): EmbedBuilder { - var alreadyExists = false - transaction { - alreadyExists = TimePlanningChannels.select { - (TimePlanningChannels.serverid eq gID) and - (TimePlanningChannels.channelid eq cID) - }.count() > 0 - } - if (!alreadyExists) { - transaction { - TimePlanningChannels.insert { - it[TimePlanningChannels.serverid] = gID - it[TimePlanningChannels.channelid] = cID - } get TimePlanningChannels.id - } + if (!TimePlanningChannelsRepository.exists(cID, gID)) { + TimePlanningChannelsRepository.write(TimePlanningChannelsData(id = -1, serverID = gID, channelID = cID)) return MessageUtil.getEmbed( - Color(0x52E01A), + EmbedColor.SUCCESS, "200: Success", "The feature was enabled in channel ${args.channel.data.name.value}", u.asUser().username + "#" + u.asUser().discriminator ) } return MessageUtil.getEmbed( - Color(0xE0311A), + EmbedColor.ERROR, "403: Forbidden", "The feature is already enabled in this channel.", u.asUser().username + "#" + u.asUser().discriminator @@ -199,33 +168,17 @@ object TimeManager : IFeature { override suspend fun disable( u: UserBehavior, - gID: String, - cID: String, + gID: Long, + cID: Long, ch: Channel, args: FeatureManageExtension.FeatureManagerArgs ): EmbedBuilder { // Check if entry exists in db - var alreadyExists = false - transaction { - alreadyExists = TimePlanningChannels.select { - (TimePlanningChannels.serverid eq gID) and - (TimePlanningChannels.channelid eq cID) - }.count() > 0 - } - if (alreadyExists) { + if (TimePlanningChannelsRepository.exists(cID, gID)) { // delete all entrys for this channel - transaction { - val matchingEntries = TimePlanningChannels.select { - (TimePlanningChannels.serverid eq gID) and - (TimePlanningChannels.channelid eq cID) - }.toList() - - matchingEntries.forEach { entry -> - TimePlanningChannels.deleteWhere { id eq entry[id] } - } - } + TimePlanningChannelsRepository.deleteFromChannelInServer(cID, gID) return MessageUtil.getEmbed( - Color(0x52E019), + EmbedColor.SUCCESS, "200: Success", "The feature was disabled.", u.asUser().username + "#" + u.asUser().discriminator @@ -233,7 +186,7 @@ object TimeManager : IFeature { } // Do nothing; not in db return MessageUtil.getEmbed( - Color(0xE0311A), + EmbedColor.ERROR, "403: Forbidden", "The feature is already disabled in this channel.", u.asUser().username + "#" + u.asUser().discriminator diff --git a/src/main/kotlin/net/moonleay/lilJudd/features/component/IFeature.kt b/src/main/kotlin/net/moonleay/lilJudd/features/component/IFeature.kt index aa27536..1145797 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/features/component/IFeature.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/features/component/IFeature.kt @@ -29,16 +29,16 @@ interface IFeature { suspend fun enable( u: UserBehavior, - gID: String, - cID: String, + gID: Long, + cID: Long, ch: Channel, args: FeatureManageExtension.FeatureManagerArgs ): EmbedBuilder suspend fun disable( u: UserBehavior, - gID: String, - cID: String, + gID: Long, + cID: Long, ch: Channel, args: FeatureManageExtension.FeatureManagerArgs ): EmbedBuilder diff --git a/src/main/kotlin/net/moonleay/lilJudd/jobs/MatchJob.kt b/src/main/kotlin/net/moonleay/lilJudd/jobs/MatchJob.kt index 394758a..6f13dfa 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/jobs/MatchJob.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/jobs/MatchJob.kt @@ -22,16 +22,11 @@ import dev.inmo.krontab.KronScheduler import dev.kord.common.entity.Snowflake import kotlinx.coroutines.Job import net.moonleay.lilJudd.Bot -import net.moonleay.lilJudd.data.entry.MatchPlanningDataData -import net.moonleay.lilJudd.data.tables.MatchPlanningData +import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository import net.moonleay.lilJudd.jobs.component.CronjobType import net.moonleay.lilJudd.jobs.component.ICronjob import net.moonleay.lilJudd.jobs.component.JobManager import net.moonleay.lilJudd.util.Logger -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.jetbrains.exposed.sql.deleteWhere -import org.jetbrains.exposed.sql.select -import org.jetbrains.exposed.sql.transactions.transaction class MatchJob( override val jobIncoming: String, @@ -48,41 +43,19 @@ class MatchJob( * */ override suspend fun jobFunction() { Logger.out("Running MatchJob \"${this.jobName}\"") - lateinit var mpdd: MatchPlanningDataData - transaction { - for (pnr in MatchPlanningData.select { - MatchPlanningData.id eq (tableId) - }) { - mpdd = MatchPlanningDataData( - pnr[MatchPlanningData.id].value, - pnr[MatchPlanningData.serverid], - pnr[MatchPlanningData.channelid], - pnr[MatchPlanningData.matchtype], - pnr[MatchPlanningData.registererid], - pnr[MatchPlanningData.roleid], - pnr[MatchPlanningData.opponentName], - pnr[MatchPlanningData.messageid], - pnr[MatchPlanningData.timestamp], - pnr[MatchPlanningData.jobstr] - ) - } - } - val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(mpdd.serverid)) + val mpdd = MatchPlanningDataRepository.get(tableId)!! + val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(mpdd.serverID)) if (guild == null) { Logger.out("Guild not found.") return } - val r = guild.getRoleOrNull(Snowflake(mpdd.roleid)) + val r = guild.getRoleOrNull(Snowflake(mpdd.roleID)) if (r == null) { Logger.out("Role not found.") return } r.delete() - transaction { - MatchPlanningData.deleteWhere { - MatchPlanningData.id eq (tableId) - } - } + MatchPlanningDataRepository.delete(tableId) Logger.out("MatchJob \"${this.jobName}\" finished.") Logger.out("Killing job \"${this.jobName}\"..") JobManager.killJob(this) diff --git a/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiFestivalAndCoopUpdateScheduler.kt b/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiFestivalAndCoopUpdateScheduler.kt new file mode 100644 index 0000000..ff299fc --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiFestivalAndCoopUpdateScheduler.kt @@ -0,0 +1,50 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.jobs + +import dev.inmo.krontab.KronScheduler +import kotlinx.coroutines.Job +import net.moonleay.lilJudd.data.api.Splatoon3ApiCache +import net.moonleay.lilJudd.data.api.type.ApiDataType +import net.moonleay.lilJudd.data.api.type.ApiRequestType +import net.moonleay.lilJudd.jobs.component.CronjobType +import net.moonleay.lilJudd.jobs.component.ICronjob +import net.moonleay.lilJudd.util.Logger + +object Splatoon3ApiFestivalAndCoopUpdateScheduler : ICronjob { + override val jobName: String + get() = "Splatoon3ApiFestivalAndCoopUpdateScheduler" + override val jobIncoming: String + get() = "0 0 0 /1 * * 0o *" // once a day + override val jobType: CronjobType + get() = CronjobType.INFINITE + override val continueJob: Boolean + get() = true + override lateinit var cronjobJob: Job + override lateinit var scheduler: KronScheduler + + override suspend fun jobFunction() { + Logger.out("Running Splatoon3ApiFestivalUpdateScheduler.") + Splatoon3ApiCache.updateData(ApiDataType.SPLATFESTS, ApiRequestType.AUTOMATIC_CACHE_UPDATE) + Logger.out("Splatoon3ApiFestivalUpdateScheduler finished.") + Logger.out("Running Splatoon3ApiCoopUpdateScheduler.") + Splatoon3ApiCache.updateData(ApiDataType.COOP, ApiRequestType.AUTOMATIC_CACHE_UPDATE) + Logger.out("Splatoon3ApiCoopUpdateScheduler finished.") + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiScheduleUpdateScheduler.kt b/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiScheduleUpdateScheduler.kt new file mode 100644 index 0000000..5c38b15 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiScheduleUpdateScheduler.kt @@ -0,0 +1,47 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.jobs + +import dev.inmo.krontab.KronScheduler +import kotlinx.coroutines.Job +import net.moonleay.lilJudd.data.api.Splatoon3ApiCache +import net.moonleay.lilJudd.data.api.type.ApiDataType +import net.moonleay.lilJudd.data.api.type.ApiRequestType +import net.moonleay.lilJudd.jobs.component.CronjobType +import net.moonleay.lilJudd.jobs.component.ICronjob +import net.moonleay.lilJudd.util.Logger + +object Splatoon3ApiScheduleUpdateScheduler : ICronjob { + override val jobName: String + get() = "Splatoon3ApiScheduleUpdateScheduler" + override val jobIncoming: String + get() = "0 0 /1 * * * 0o *" //Every hour + override val jobType: CronjobType + get() = CronjobType.INFINITE + override val continueJob: Boolean + get() = true + override lateinit var cronjobJob: Job + override lateinit var scheduler: KronScheduler + + override suspend fun jobFunction() { + Logger.out("Running Splatoon3ApiScheduleUpdateScheduler.") + Splatoon3ApiCache.updateData(ApiDataType.SCHEDULES, ApiRequestType.AUTOMATIC_CACHE_UPDATE) + Logger.out("Splatoon3ApiScheduleUpdateScheduler finished.") + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiSplatnetGearUpdateScheduler.kt b/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiSplatnetGearUpdateScheduler.kt new file mode 100644 index 0000000..51048f2 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/jobs/Splatoon3ApiSplatnetGearUpdateScheduler.kt @@ -0,0 +1,47 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.jobs + +import dev.inmo.krontab.KronScheduler +import kotlinx.coroutines.Job +import net.moonleay.lilJudd.data.api.Splatoon3ApiCache +import net.moonleay.lilJudd.data.api.type.ApiDataType +import net.moonleay.lilJudd.data.api.type.ApiRequestType +import net.moonleay.lilJudd.jobs.component.CronjobType +import net.moonleay.lilJudd.jobs.component.ICronjob +import net.moonleay.lilJudd.util.Logger + +object Splatoon3ApiSplatnetGearUpdateScheduler : ICronjob { + override val jobName: String + get() = "Splatoon3ApiSplatnetGearUpdateScheduler" + override val jobIncoming: String + get() = "0 0 /6 * * * 0o *" //Every 6 hours + override val jobType: CronjobType + get() = CronjobType.INFINITE + override val continueJob: Boolean + get() = true + override lateinit var cronjobJob: Job + override lateinit var scheduler: KronScheduler + + override suspend fun jobFunction() { + Logger.out("Running Splatoon3ApiSplatnetGearUpdateScheduler.") + Splatoon3ApiCache.updateData(ApiDataType.SPLATNETGEAR, ApiRequestType.AUTOMATIC_CACHE_UPDATE) + Logger.out("Splatoon3ApiSplatnetGearUpdateScheduler finished.") + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/jobs/StatusUpdater.kt b/src/main/kotlin/net/moonleay/lilJudd/jobs/StatusUpdater.kt new file mode 100644 index 0000000..7df554b --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/jobs/StatusUpdater.kt @@ -0,0 +1,67 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.jobs + +import dev.inmo.krontab.KronScheduler +import dev.kord.common.entity.PresenceStatus +import kotlinx.coroutines.Job +import net.moonleay.lilJudd.Bot +import net.moonleay.lilJudd.data.api.Splatoon3Api +import net.moonleay.lilJudd.jobs.component.CronjobType +import net.moonleay.lilJudd.jobs.component.ICronjob + +object StatusUpdater : ICronjob { + override val jobName: String + get() = "StatusUpdater" + override val jobIncoming: String + get() = "/5 * * * * * 0o *" //Every 5 seconds + override val jobType: CronjobType + get() = CronjobType.INFINITE + override val continueJob: Boolean + get() = true + override lateinit var cronjobJob: Job + override lateinit var scheduler: KronScheduler + + private var statusList = listOf() + private var index = 0 + + override suspend fun jobFunction() { + refreshStatusList(System.currentTimeMillis()) + Bot.bot.kordRef.editPresence { + this.status = PresenceStatus.DoNotDisturb + this.playing(statusList[index]) + } + ++index + if (index >= statusList.size) { + index = 0 + } + } + + fun refreshStatusList(timestamp: Long) { + statusList = listOf( + Splatoon3Api.getRegularMapsFormatted(timestamp), + Splatoon3Api.getSeriesModeFormatted(timestamp), + Splatoon3Api.getSeriesMapsFormatted(timestamp), + Splatoon3Api.getOpenModeFormatted(timestamp), + Splatoon3Api.getOpenMapFormatted(timestamp), + Splatoon3Api.getXModeFormatted(timestamp), + Splatoon3Api.getXMapFormatted(timestamp), + ) + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/tables/TimePlanningChannels.kt b/src/main/kotlin/net/moonleay/lilJudd/util/EmbedColor.kt similarity index 76% rename from src/main/kotlin/net/moonleay/lilJudd/data/tables/TimePlanningChannels.kt rename to src/main/kotlin/net/moonleay/lilJudd/util/EmbedColor.kt index a746aa1..cb3e983 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/tables/TimePlanningChannels.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/util/EmbedColor.kt @@ -16,11 +16,13 @@ * along with this program. If not, see . */ -package net.moonleay.lilJudd.data.tables +package net.moonleay.lilJudd.util -import org.jetbrains.exposed.dao.id.IntIdTable +import dev.kord.common.Color -object TimePlanningChannels : IntIdTable() { - var serverid = varchar("serverid", 50) - val channelid = varchar("channelid", 50) +enum class EmbedColor(val color: Color) { + ERROR(Color(0xE0311A)), + WARNING(Color(0xFFA500)), + SUCCESS(Color(0x52E01A)), + INFO(Color(0x4C4645)), } diff --git a/src/main/kotlin/net/moonleay/lilJudd/util/EmbedUtil.kt b/src/main/kotlin/net/moonleay/lilJudd/util/EmbedUtil.kt index d367709..17615b3 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/util/EmbedUtil.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/util/EmbedUtil.kt @@ -41,17 +41,26 @@ object EmbedUtil { fun getMatchButtons(): ActionRowBuilder { val ar = ActionRowBuilder() ar.interactionButton(ButtonStyle.Success, "public.edit.btn.matchmanagement.accept") { - this.label = "Sign me up!" + this.label = "I'm in!" } - ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.matchmanagement.cancel") { - this.label = "Cancel" + ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.matchmanagement.decline") { + this.label = "I'm out!" } + /* + ar.interactionButton(ButtonStyle.Secondary, "public.edit.btn.matchmanagement.cancel") { + this.label = "Cancel this match..." + } */ return ar } fun replaceXWithYinValuesAtTable(x: String, y: String, e: Embed, table: Int): EmbedBuilder { - val ebb = MessageUtil.getAClonedEmbedd(e) - for ((i, f) in e.fields.withIndex()) { + return replaceXWithYinValuesAtTable(x, y, MessageUtil.getAClonedEmbed(e), table) + } + + fun replaceXWithYinValuesAtTable(x: String, y: String, ebb: EmbedBuilder, table: Int): EmbedBuilder { + val ebbb = MessageUtil.getAClonedEmbed(ebb) + ebbb.fields = mutableListOf() + for ((i, f) in ebb.fields.withIndex()) { val fb = EmbedBuilder.Field() fb.name = f.name if (i == table - 1) { @@ -66,14 +75,14 @@ object EmbedUtil { } else fb.value = f.value fb.inline = true - ebb.fields.add(fb) + ebbb.fields.add(fb) } - return ebb + return ebbb } fun getAllUsersInTheFirstXTables(amountOfTables: Int, e: Embed): List { val users = mutableListOf() - for (i in 0 until amountOfTables - 1) { + for (i in 0 until amountOfTables) { val f = e.fields[i] if (!f.value.contains("@")) continue // check next one. this one does not have any entries @@ -87,8 +96,13 @@ object EmbedUtil { } fun addXToValuesAtTable(x: String, e: Embed, table: Int): EmbedBuilder { - val ebb = MessageUtil.getAClonedEmbedd(e) - for ((i, f) in e.fields.withIndex()) { + return addXToValuesAtTable(x, MessageUtil.getAClonedEmbed(e), table) + } + + fun addXToValuesAtTable(x: String, ebb: EmbedBuilder, table: Int): EmbedBuilder { + val ebbb = MessageUtil.getAClonedEmbed(ebb) + ebbb.fields = mutableListOf() + ebb.fields.forEachIndexed { i, f -> val fb = EmbedBuilder.Field() fb.name = f.name if (i == table - 1) @@ -105,9 +119,9 @@ object EmbedUtil { } fb.inline = true - ebb.fields.add(fb) + ebbb.fields.add(fb) } - return ebb + return ebbb } } diff --git a/src/main/kotlin/net/moonleay/lilJudd/util/MessageUtil.kt b/src/main/kotlin/net/moonleay/lilJudd/util/MessageUtil.kt index dc0a34a..6dfb545 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/util/MessageUtil.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/util/MessageUtil.kt @@ -22,7 +22,6 @@ import com.kotlindiscord.kord.extensions.commands.Arguments import com.kotlindiscord.kord.extensions.commands.application.slash.PublicSlashCommandContext import com.kotlindiscord.kord.extensions.components.forms.ModalForm import com.kotlindiscord.kord.extensions.types.respond -import dev.kord.common.Color import dev.kord.core.entity.Embed import dev.kord.rest.builder.message.EmbedBuilder import java.time.LocalDateTime @@ -34,7 +33,7 @@ object MessageUtil { ///Send an embedded message as a reply suspend fun sendEmbedForPublicSlashCommand( ctx: PublicSlashCommandContext, - color: Color, + color: EmbedColor, title: String, description: String ) { @@ -53,7 +52,7 @@ object MessageUtil { ///Send an embedded message with an image as a reply suspend fun sendEmbedForPublicSlashCommandWithImage( ctx: PublicSlashCommandContext, - color: Color, + color: EmbedColor, title: String, description: String, thumbnailUrl: String @@ -71,17 +70,39 @@ object MessageUtil { } } - ///Get a cloned embedded message, missing only the fields - fun getAClonedEmbedd(e: Embed): EmbedBuilder { + ///Get a cloned embedded message + fun getAClonedEmbed(e: Embed): EmbedBuilder { val ebb = EmbedBuilder() ebb.color = e.color ebb.title = e.title + e.fields.forEach { + val fb = EmbedBuilder.Field() + fb.name = it.name + fb.value = it.value + fb.inline = it.inline + ebb.fields.add(fb) + } + ebb.description = e.description + return ebb + } + + fun getAClonedEmbed(e: EmbedBuilder): EmbedBuilder { + val ebb = EmbedBuilder() + ebb.color = e.color + ebb.title = e.title + e.fields.forEach { + val fb = EmbedBuilder.Field() + fb.name = it.name + fb.value = it.value + fb.inline = it.inline + ebb.fields.add(fb) + } ebb.description = e.description return ebb } fun getEmbedWithTableWithFooter( - color: Color, + color: EmbedColor, title: String, description: String, values: Map>?, @@ -95,7 +116,7 @@ object MessageUtil { ///Get an embedded msg with image, title and description fun getEmbedWithTable( - color: Color, + color: EmbedColor, title: String, description: String, values: Map>? @@ -118,20 +139,20 @@ object MessageUtil { ///Get an embedded msg with title and description fun getEmbedSmall( - color: Color, + color: EmbedColor, title: String, description: String ): EmbedBuilder { val ebb = EmbedBuilder() ebb.title = title ebb.description = description - ebb.color = color + ebb.color = color.color return ebb } ///Get an embedded msg with title, description and a src fun getEmbed( - color: Color, + color: EmbedColor, title: String, description: String, source: String @@ -145,7 +166,7 @@ object MessageUtil { ///Get an embedded msg with image, title, description and a src fun getEmbedWithImage( - color: Color, + color: EmbedColor, title: String, description: String, source: String, diff --git a/src/main/kotlin/net/moonleay/lilJudd/util/NetUtil.kt b/src/main/kotlin/net/moonleay/lilJudd/util/NetUtil.kt new file mode 100644 index 0000000..5b43bbc --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/util/NetUtil.kt @@ -0,0 +1,45 @@ +/* + * lilJudd + * Copyright (C) 2023 moonleay + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.moonleay.lilJudd.util + +import java.net.URL +import javax.net.ssl.HttpsURLConnection + +object NetUtil { + fun GETJsonData(urlIN: String, userAgent: String): String { + val startTime = System.currentTimeMillis() + val url = URL(urlIN) + val connection = url.openConnection() as HttpsURLConnection + connection.requestMethod = "GET" + connection.setRequestProperty("User-Agent", userAgent) + connection.setRequestProperty("Accept", "application/json") + val responseCode = connection.responseCode + val timeDiff = System.currentTimeMillis() - startTime + Logger.out("GET took $timeDiff ms (from: $urlIN, as $userAgent)") + return if (responseCode == HttpsURLConnection.HTTP_OK) { + val inputStream = connection.inputStream + val inputStreamReader = inputStream.reader() + val inputAsString = inputStreamReader.readText() + inputStream.close() + inputAsString + } else { + "Error $responseCode" + } + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/util/TimeUtil.kt b/src/main/kotlin/net/moonleay/lilJudd/util/TimeUtil.kt index c3c3e54..5287bc3 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/util/TimeUtil.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/util/TimeUtil.kt @@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit object TimeUtil { - fun getTimeFormatedShortend(time2: Long): String { + fun getTimeFormatedShortend(time2: Long, showS: Boolean): String { var time = time2 val days: Long = TimeUnit.MILLISECONDS .toDays(time) @@ -52,7 +52,7 @@ object TimeUtil { if (minutes >= 1) { s += minutes.toString() + "m " } - if (seconds >= 1 && hours < 1) { + if (seconds >= 1 && hours < 1 && showS) { s += seconds.toString() + "s" } if (s.isEmpty() || s.isBlank()) { @@ -158,4 +158,17 @@ object TimeUtil { val zdt_ = zdt.minusHours(1) return "0 ${zdt_.minute} ${zdt_.hour} ${zdt_.dayOfMonth - 1} ${zdt_.month.value - 1} ${zdt_.year}"// 0o *w" } + + fun deformatJSONTime(inp: String, zone: String): Long { + // 2023-10-05T08:00:00Z + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") + val localDateTime = LocalDateTime.parse(inp, formatter) + val zoneId = ZoneId.of(zone) // TODO: Add the possibility to set your timezone + return ZonedDateTime.of(localDateTime, zoneId).toEpochSecond() * 1000 + } + + fun getTimeDifferenceFormatted(start: Long, end: Long): String { + val diff = end - start + return getTimeFormatedShortend(diff, false) + } } diff --git a/src/main/templates/net/moonleay/lilJudd/build/BuildConstants.kt b/src/main/templates/net/moonleay/lilJudd/build/BuildConstants.kt index fdcf269..d75d861 100644 --- a/src/main/templates/net/moonleay/lilJudd/build/BuildConstants.kt +++ b/src/main/templates/net/moonleay/lilJudd/build/BuildConstants.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package net.moonleay.botendo.build +package net.moonleay.liljudd.build internal object BuildConstants { const val version = "${version}"