From b45d8ffd6e74d2a88327154018cb8800b3df5197 Mon Sep 17 00:00:00 2001 From: moonleay Date: Mon, 5 Jun 2023 12:10:25 +0200 Subject: [PATCH 1/4] chore: progress commit. refactored TimePlanner, added stuff to Feature Manage Extension, added db stuff Signed-off-by: limited_dev --- README.md | 3 +- src/main/kotlin/net/moonleay/lilJudd/Bot.kt | 4 +- .../data/entry/PlanningNotifierRolesData.kt | 26 ++++++++++ ...ifyerRoles.kt => PlanningNotifierRoles.kt} | 3 +- .../extensions/FeatureManageExtension.kt | 51 ++++++++----------- .../lilJudd/features/PlanningNotifier.kt | 36 +++++++++++++ .../{TimePlanner.kt => TimeManager.kt} | 42 +++++++++++---- 7 files changed, 122 insertions(+), 43 deletions(-) create mode 100644 src/main/kotlin/net/moonleay/lilJudd/data/entry/PlanningNotifierRolesData.kt rename src/main/kotlin/net/moonleay/lilJudd/data/tables/{PlanningNotifyerRoles.kt => PlanningNotifierRoles.kt} (91%) create mode 100644 src/main/kotlin/net/moonleay/lilJudd/features/PlanningNotifier.kt rename src/main/kotlin/net/moonleay/lilJudd/features/{TimePlanner.kt => TimeManager.kt} (71%) diff --git a/README.md b/README.md index 2b9d0bc..4e4c0f6 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,10 @@ A Discord Bot for Splatoon Teams - Features - Time Planner -- Make the bot send messages and reactions into a selected channel in order to make planning easier -## Maybe upcoming features +## (Maybe) upcoming features - Match Planner (Send Notifications some time before a match starts) +- Planning Notifier (Make it possible to ping people, who have time at a specific time) - Game Tracker (Save the results of the last matches) - Replay Saver (Maybe; will save the replay code to a database) diff --git a/src/main/kotlin/net/moonleay/lilJudd/Bot.kt b/src/main/kotlin/net/moonleay/lilJudd/Bot.kt index eef040b..311616d 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/Bot.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/Bot.kt @@ -32,7 +32,7 @@ import net.moonleay.lilJudd.data.CredentialManager import net.moonleay.lilJudd.data.DB import net.moonleay.lilJudd.extensions.FeatureManageExtension import net.moonleay.lilJudd.extensions.VersionExtension -import net.moonleay.lilJudd.features.TimePlanner +import net.moonleay.lilJudd.features.TimeManager import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.MessageUtil import kotlin.system.exitProcess @@ -68,7 +68,7 @@ object Bot { // Register the TimePlanner thread val coroutineJob = GlobalScope.launch { - TimePlanner.registerThread() + TimeManager.registerThread() } // Add a shutdown hook to cancel the coroutine when the application is terminated diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/entry/PlanningNotifierRolesData.kt b/src/main/kotlin/net/moonleay/lilJudd/data/entry/PlanningNotifierRolesData.kt new file mode 100644 index 0000000..0798ccc --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/data/entry/PlanningNotifierRolesData.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.entry + +data class PlanningNotifierRolesData( + val serverID: String, + val channelId: String, + val hastimeroleid: String, + val wantstobenotifid: String +) diff --git a/src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifyerRoles.kt b/src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifierRoles.kt similarity index 91% rename from src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifyerRoles.kt rename to src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifierRoles.kt index 069bcc0..65e8b0e 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifyerRoles.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/data/tables/PlanningNotifierRoles.kt @@ -20,10 +20,9 @@ package net.moonleay.lilJudd.data.tables import org.jetbrains.exposed.dao.id.IntIdTable -object PlanningNotifyerRoles : IntIdTable() { +object PlanningNotifierRoles : IntIdTable() { var serverid = varchar("serverid", 50) var channelid = varchar("channelid", 50) var hastimeroleid = varchar("hastimeroleid", 50) - var hastovoteid = varchar("hastovoteid", 50) var wantstobenotifid = varchar("wantstobenotifid", 50) } diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt index 43cfbd4..582a079 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/extensions/FeatureManageExtension.kt @@ -29,7 +29,7 @@ import dev.kord.common.Color import dev.kord.common.entity.Permission import dev.kord.common.entity.Snowflake import dev.kord.core.behavior.createRole -import net.moonleay.lilJudd.data.tables.PlanningNotifyerRoles +import net.moonleay.lilJudd.data.tables.PlanningNotifierRoles import net.moonleay.lilJudd.data.tables.TimePlanningChannels import net.moonleay.lilJudd.extensions.component.EnableOrDisable import net.moonleay.lilJudd.extensions.component.FeatureEnum @@ -45,7 +45,7 @@ class FeatureManageExtension : Extension() { /* * Note: This has to be rewritten at some point to better support more features - * and remove this mess of a class. + * and improve this mess of a class. * */ override suspend fun setup() { publicSlashCommand(::FeatureManagerArgs) { @@ -60,7 +60,7 @@ class FeatureManageExtension : Extension() { MessageUtil.getEmbed( Color(0xE0311A), "403: Forbidden", - "You cannot edit features, as you don't have the Administratior permission.", + "You cannot edit features, as you don't have the Administrator permission.", u.asUser().username + "#" + u.asUser().discriminator ) ) @@ -116,37 +116,31 @@ class FeatureManageExtension : Extension() { FeatureEnum.PLANNINGNOTIFIER -> { var alreadyExists = false transaction { - alreadyExists = PlanningNotifyerRoles.select { - (PlanningNotifyerRoles.serverid eq gID) and (PlanningNotifyerRoles.channelid eq cID) + alreadyExists = PlanningNotifierRoles.select { + (PlanningNotifierRoles.serverid eq gID) and (PlanningNotifierRoles.channelid eq cID) }.count() > 0 } if (!alreadyExists) { - val hasToVoteRole = this.guild!!.createRole { - this.name = "Hasn't voted [${channel.data.name.value}]" - this.mentionable = true - } - val htvr = hasToVoteRole.id.toString() val hasTimeRole = this.guild!!.createRole { - this.name = "Has time [${channel.data.name.value}]" + this.name = "available [${channel.data.name.value}]" this.mentionable = true } val htr = hasTimeRole.id.toString() val wantsNotifsRole = this.guild!!.createRole { - this.name = "Wants to be notified [${channel.data.name.value}]" + this.name = "notifications [${channel.data.name.value}]" this.mentionable = true } val wnr = wantsNotifsRole.id.toString() transaction { - PlanningNotifyerRoles.insert { - it[PlanningNotifyerRoles.serverid] = gID - it[PlanningNotifyerRoles.channelid] = cID - it[PlanningNotifyerRoles.hastovoteid] = htvr - it[PlanningNotifyerRoles.hastimeroleid] = htr - it[PlanningNotifyerRoles.wantstobenotifid] = wnr - } get PlanningNotifyerRoles.id + PlanningNotifierRoles.insert { + it[PlanningNotifierRoles.serverid] = gID + it[PlanningNotifierRoles.channelid] = cID + it[PlanningNotifierRoles.hastimeroleid] = htr + it[PlanningNotifierRoles.wantstobenotifid] = wnr + } get PlanningNotifierRoles.id } this.respond { @@ -154,7 +148,7 @@ class FeatureManageExtension : Extension() { MessageUtil.getEmbed( Color(0x52E01A), "200: Success", - "The feature was enabled in channel ${args.channel.data.name.value} with roles ${hasToVoteRole.mention}, ${hasTimeRole.mention} & ${wantsNotifsRole.mention}.", + "The feature was enabled in channel ${args.channel.data.name.value} with roles ${hasTimeRole.mention} & ${wantsNotifsRole.mention}.", u.asUser().username + "#" + u.asUser().discriminator ) ) @@ -223,28 +217,27 @@ class FeatureManageExtension : Extension() { FeatureEnum.PLANNINGNOTIFIER -> { var alreadyExists = false transaction { - alreadyExists = PlanningNotifyerRoles.select { - (PlanningNotifyerRoles.serverid eq gID) and (PlanningNotifyerRoles.channelid eq cID) + alreadyExists = PlanningNotifierRoles.select { + (PlanningNotifierRoles.serverid eq gID) and (PlanningNotifierRoles.channelid eq cID) }.count() > 0 } if (alreadyExists) { var matchingEntries: List = mutableListOf() transaction { - matchingEntries = PlanningNotifyerRoles.select { - (PlanningNotifyerRoles.serverid eq gID) and - (PlanningNotifyerRoles.channelid eq cID) + matchingEntries = PlanningNotifierRoles.select { + (PlanningNotifierRoles.serverid eq gID) and + (PlanningNotifierRoles.channelid eq cID) }.toList() } for (e in matchingEntries) { - this.guild!!.getRoleOrNull(Snowflake(e[PlanningNotifyerRoles.hastovoteid]))?.delete() - this.guild!!.getRoleOrNull(Snowflake(e[PlanningNotifyerRoles.hastimeroleid]))?.delete() - this.guild!!.getRoleOrNull(Snowflake(e[PlanningNotifyerRoles.wantstobenotifid])) + this.guild!!.getRoleOrNull(Snowflake(e[PlanningNotifierRoles.hastimeroleid]))?.delete() + this.guild!!.getRoleOrNull(Snowflake(e[PlanningNotifierRoles.wantstobenotifid])) ?.delete() } transaction { matchingEntries.forEach { entry -> - PlanningNotifyerRoles.deleteWhere { id eq entry[id] } + PlanningNotifierRoles.deleteWhere { id eq entry[id] } } } this.respond { diff --git a/src/main/kotlin/net/moonleay/lilJudd/features/PlanningNotifier.kt b/src/main/kotlin/net/moonleay/lilJudd/features/PlanningNotifier.kt new file mode 100644 index 0000000..3aab7e5 --- /dev/null +++ b/src/main/kotlin/net/moonleay/lilJudd/features/PlanningNotifier.kt @@ -0,0 +1,36 @@ +/* + * 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.features + +import dev.inmo.krontab.buildSchedule +import dev.inmo.krontab.doInfinity +import net.moonleay.lilJudd.util.Logger + +object PlanningNotifier { + suspend fun registerThread() { + Logger.out("Adding ping scheduler...") + val scheduler = buildSchedule("0 00 23 * * * 0o *") // 0 0 4 * * * 0o 1w // 0o is UTC + scheduler.doInfinity { + Logger.out("Starting to update roles...") + + Logger.out("Done! Until tomorrow! <3 ") + } + + } +} diff --git a/src/main/kotlin/net/moonleay/lilJudd/features/TimePlanner.kt b/src/main/kotlin/net/moonleay/lilJudd/features/TimeManager.kt similarity index 71% rename from src/main/kotlin/net/moonleay/lilJudd/features/TimePlanner.kt rename to src/main/kotlin/net/moonleay/lilJudd/features/TimeManager.kt index a8bb189..403dec8 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/features/TimePlanner.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/features/TimeManager.kt @@ -27,6 +27,8 @@ import dev.kord.core.entity.channel.MessageChannel 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.util.ButtonUtil import net.moonleay.lilJudd.util.Logger @@ -37,7 +39,7 @@ import java.time.ZoneId import java.time.ZonedDateTime -object TimePlanner { +object TimeManager { /* /--------------- Seconds | /------------- Minutes | | /----------- Hours @@ -49,23 +51,43 @@ object TimePlanner { * * * * * * 0o *w*/ suspend fun registerThread() { - Logger.out("Adding scheduler...") - val scheduler = buildSchedule("0 0 4 * * * 0o 1w") // 0 0 4 * * * 0o 1w // 0o is UTC + Logger.out("Adding message scheduler...") + val scheduler = buildSchedule("0 00 23 * * * 0o *") // 0 0 4 * * * 0o 1w // 0o is UTC scheduler.doInfinity { Logger.out("Starting to notify...") - val channelList = mutableListOf() + + + // ChannelID, ServerID + val channelList = mutableMapOf() + // ChannelID, Data + val roleList = mutableMapOf() + transaction { for (tp in TimePlanningChannels.selectAll()) { - channelList.add(Snowflake(tp[TimePlanningChannels.channelid])) + 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()) { + roleList[Snowflake(pnr[PlanningNotifierRoles.channelid])] = PlanningNotifierRolesData( + pnr[PlanningNotifierRoles.serverid], + pnr[PlanningNotifierRoles.channelid], + pnr[PlanningNotifierRoles.hastimeroleid], + pnr[PlanningNotifierRoles.wantstobenotifid] + ) + Logger.out("Have to ping roles: ${pnr[PlanningNotifierRoles.wantstobenotifid]}}") + } } - Logger.out("${channelList.count()} Channels to notify!") - for (ch in channelList) { + Logger.out("${channelList.count()} Channels to notify with ${roleList.count()} Roles to ping!") + for (ch in channelList.keys) { 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)!! c.createMessage { + if (roleList[ch] != null) { + this.content = "<@&${Snowflake(roleList[ch]?.wantstobenotifid!!)}>" + } this.embeds.add( MessageUtil.getEmbed( Color(0X4C4645), @@ -75,7 +97,7 @@ object TimePlanner { ) ) } - delay(3000) + delay(2000) var then = ZonedDateTime.now(ZoneId.of("Europe/Berlin")).withHour(4).withMinute(0).withSecond(0) repeat(7) { c.createMessage { @@ -96,8 +118,10 @@ object TimePlanner { this.components.addAll(ButtonUtil.getTimePlannerButtons().components) } } - then = then.plusDays(1).withHour(20).withMinute(24).withSecond(0) + then = then.plusDays(1).withHour(4).withMinute(0).withSecond(0) + Logger.out("Finished sending day $it") + delay(1000) } Logger.out("Finished with ${c.data.guildId.value}") From 8bebe08b150301a956c7213121332b93812a7d3d Mon Sep 17 00:00:00 2001 From: limited_dev Date: Thu, 15 Jun 2023 08:06:35 +0200 Subject: [PATCH 2/4] feat: added .dockerignore Signed-off-by: limited_dev --- .dockerignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0b6a882 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +**.nils +/run +/run/ From 9885466ed580aa8b1e1d00338699a61f01332adb Mon Sep 17 00:00:00 2001 From: limited_dev Date: Thu, 15 Jun 2023 08:07:15 +0200 Subject: [PATCH 3/4] !fix: removed not properly usable sendplanner command Signed-off-by: limited_dev --- .../extensions/SendPlannerExtension.kt | 67 ++++++++----------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt b/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt index 4d3defb..2482bbf 100644 --- a/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt +++ b/src/main/kotlin/net/moonleay/lilJudd/extensions/SendPlannerExtension.kt @@ -18,8 +18,6 @@ package net.moonleay.lilJudd.extensions -import com.kotlindiscord.kord.extensions.commands.Arguments -import com.kotlindiscord.kord.extensions.commands.converters.impl.int import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.types.respond @@ -44,11 +42,11 @@ class SendPlannerExtension : Extension() { get() = false override suspend fun setup() { - publicSlashCommand(::PlannerArgs) { + publicSlashCommand() { name = "sendplanner" description = "Send the planner for the current and x next weeks" this.action { - if (this.arguments.weeks == 0 || !this.member!!.asMember(this.guild!!.id) + if (!this.member!!.asMember(this.guild!!.id) .hasPermission(Permission.Administrator) ) { val res = this.respond { @@ -65,42 +63,39 @@ class SendPlannerExtension : Extension() { var then = ZonedDateTime.now(ZoneId.of("Europe/Berlin")).withDayOfMonth(getMondayDayOfMonth()).withHour(4) .withMinute(0).withSecond(0) - repeat(this.arguments.weeks) { + c.createMessage { + this.embeds.add( + MessageUtil.getEmbed( + Color(0X4C4645), + "Time Planning Feature", + "Do you have time on the following Days?", + "Automated Message" + ) + ) + } + delay(1000) + repeat(7) { c.createMessage { this.embeds.add( - MessageUtil.getEmbed( + MessageUtil.getEmbedWithTable( Color(0X4C4645), - "Time Planning Feature", - "Do you have time on the following Days?", - "Automated Message" - ) - ) - } - delay(1000) - repeat(7) { - c.createMessage { - this.embeds.add( - MessageUtil.getEmbedWithTable( - Color(0X4C4645), - "", - "${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday", - mapOf( - "Is available" to listOf(), - "May be available" to listOf(), - "Is not available" to listOf() - ) + "", + "${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday", + mapOf( + "Is available" to listOf(), + "May be available" to listOf(), + "Is not available" to listOf() ) ) + ) - this.actionRow { - this.components.addAll(ButtonUtil.getTimePlannerButtons().components) - } + this.actionRow { + this.components.addAll(ButtonUtil.getTimePlannerButtons().components) } - then = then.plusDays(1).withHour(4).withMinute(0).withSecond(0) - Logger.out("Finished sending day $it") - delay(1000) } - Logger.out("Finished week $it") + then = then.plusDays(1).withHour(4).withMinute(0).withSecond(0) + Logger.out("Finished sending day $it") + delay(1000) } Logger.out("Finished with ${c.data.guildId.value}") } @@ -112,12 +107,4 @@ class SendPlannerExtension : Extension() { val monday = now.with(DayOfWeek.MONDAY) return monday.dayOfMonth } - - inner class PlannerArgs : Arguments() { - val weeks by int { - name = "weeks" - description = "Amount of weeks to send. Needs to be at least 1." - minValue = 1 - } - } } From bcf9b2cf9ba2671e8713ff1410a54bc03e85dd7f Mon Sep 17 00:00:00 2001 From: limited_dev Date: Thu, 15 Jun 2023 08:07:26 +0200 Subject: [PATCH 4/4] chore: bump version Signed-off-by: limited_dev --- build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 53e1b78..4d4b3c5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,7 @@ 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.2.0" + ?: "2.2.1" val kordver = "1.5.6" val coroutinesver = "1.1.0" @@ -88,8 +88,6 @@ dependencies { shadow("org.slf4j:slf4j-simple:2.0.3") //Database - shadow("io.ktor:ktor-client-core:$ktor_version") - shadow("io.ktor:ktor-client-cio:$ktor_version") shadow("org.jetbrains.exposed:exposed-core:$exposedver") shadow("org.jetbrains.exposed:exposed-dao:$exposedver") shadow("org.jetbrains.exposed:exposed-jdbc:$exposedver") @@ -97,6 +95,8 @@ dependencies { //Korntab 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") }