commit 22052049be5a784f22681ccd6833a9ea2b4889f1 Author: lucasdpt Date: Sun Nov 2 21:02:40 2025 +0100 feat: initial commit diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml new file mode 100644 index 0000000..a1cf3a8 --- /dev/null +++ b/.gitea/workflows/release.yaml @@ -0,0 +1,30 @@ +name: Release + +on: + push: + branches: + - master + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + release: + runs-on: ubuntu-latest + container: git.tools.ldpt.fr/actions/ci-image:1.0.0 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Maven settings.xml + env: + MAVEN_SETTINGS: ${{ secrets.MAVEN_SETTINGS }} + run: | + mkdir -p .m2 + echo "$MAVEN_SETTINGS" > .m2/settings.xml + + - name: Release with semantic-release + run: | + npx semantic-release \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..667aaef --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 0000000..fb5d97f --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,23 @@ +{ + "branches": ["master"], + "tagFormat": "${version}", + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + [ + "@semantic-release/exec", + { + "prepareCmd": "mvn versions:set -DnewVersion=${nextRelease.version} -DgenerateBackupPoms=false", + "publishCmd": "mvn clean deploy --settings .m2/settings.xml" + } + ], + [ + "@semantic-release/git", + { + "assets": ["pom.xml", "CHANGELOG.md"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ] + ] +} \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..3d9b2f2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.5.7 + + + fr.lucasdupont + spring-jda-starter + 0.0.1-SNAPSHOT + spring-jda-starter + Starter for JDA project + + 21 + 2.2.0 + 6.1.1 + + + + + gitea + https://git.tools.ldpt.fr/api/packages/hestia/maven + + + + + + org.springframework.boot + spring-boot-starter + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib + + + + net.dv8tion + JDA + ${jda.version} + + + club.minnced + opus-java + + + + + + + ${project.basedir}/src/main/kotlin + + + org.springframework.boot + spring-boot-maven-plugin + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + -Xjsr305=strict + + + spring + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + + + + + diff --git a/src/main/kotlin/fr/lucasdupont/command/Command.kt b/src/main/kotlin/fr/lucasdupont/command/Command.kt new file mode 100644 index 0000000..226b2e9 --- /dev/null +++ b/src/main/kotlin/fr/lucasdupont/command/Command.kt @@ -0,0 +1,31 @@ +package fr.lucasdupont.gaytabot.command + +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent +import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions +import net.dv8tion.jda.api.interactions.commands.build.OptionData +import net.dv8tion.jda.api.interactions.commands.build.SubcommandData + +interface Command { + + val name: String + val description: String + + val options: List + get() = emptyList() + + val neededPermissions: DefaultMemberPermissions? + get() = null + + val subcommands: List + get() = emptyList() + + val subcommandGroups: List + get() = emptyList() + + @Throws(Exception::class) + fun execute(event: SlashCommandInteractionEvent) + + fun toSubcommandData(): SubcommandData = + SubcommandData(name, description).addOptions(options) + +} \ No newline at end of file diff --git a/src/main/kotlin/fr/lucasdupont/command/CommandMapper.kt b/src/main/kotlin/fr/lucasdupont/command/CommandMapper.kt new file mode 100644 index 0000000..0918cee --- /dev/null +++ b/src/main/kotlin/fr/lucasdupont/command/CommandMapper.kt @@ -0,0 +1,23 @@ +package fr.lucasdupont.gaytabot.command + +import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData +import net.dv8tion.jda.internal.interactions.CommandDataImpl + +fun Command.toCommandData(): CommandDataImpl = CommandDataImpl(name, description).apply { + addOptions(options) + neededPermissions?.let { setDefaultPermissions(it) } + + if (subcommands.isNotEmpty()) { + addSubcommands(subcommands.map { toSubcommandData() }) + } + + if (subcommandGroups.isNotEmpty()) { + addSubcommandGroups( + subcommandGroups.map { group -> + SubcommandGroupData( + group.name, + group.description + ).addSubcommands(group.subcommands.map { toSubcommandData() }) + }) + } +} \ No newline at end of file diff --git a/src/main/kotlin/fr/lucasdupont/command/SubCommandGroup.kt b/src/main/kotlin/fr/lucasdupont/command/SubCommandGroup.kt new file mode 100644 index 0000000..95295a1 --- /dev/null +++ b/src/main/kotlin/fr/lucasdupont/command/SubCommandGroup.kt @@ -0,0 +1,7 @@ +package fr.lucasdupont.gaytabot.command + +data class SubCommandGroup( + val name: String, + val description: String, + val subCommands: List +) diff --git a/src/main/kotlin/fr/lucasdupont/configuration/JdaConfiguration.kt b/src/main/kotlin/fr/lucasdupont/configuration/JdaConfiguration.kt new file mode 100644 index 0000000..1e67b75 --- /dev/null +++ b/src/main/kotlin/fr/lucasdupont/configuration/JdaConfiguration.kt @@ -0,0 +1,13 @@ +package fr.lucasdupont.configuration + +import net.dv8tion.jda.api.OnlineStatus +import net.dv8tion.jda.api.utils.cache.CacheFlag +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties("jda") +class JdaConfiguration { + var token: String? = null + var onlineStatus: OnlineStatus = OnlineStatus.ONLINE + var cacheFlags: Set = emptySet() + var activity: String? = null +} \ No newline at end of file diff --git a/src/main/kotlin/fr/lucasdupont/service/JdaService.kt b/src/main/kotlin/fr/lucasdupont/service/JdaService.kt new file mode 100644 index 0000000..51bc84b --- /dev/null +++ b/src/main/kotlin/fr/lucasdupont/service/JdaService.kt @@ -0,0 +1,75 @@ +package fr.lucasdupont.service + +import fr.lucasdupont.configuration.JdaConfiguration +import fr.lucasdupont.gaytabot.command.Command +import fr.lucasdupont.gaytabot.command.toCommandData +import net.dv8tion.jda.api.JDA +import net.dv8tion.jda.api.JDABuilder +import net.dv8tion.jda.api.entities.Activity +import net.dv8tion.jda.api.events.GenericEvent +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent +import net.dv8tion.jda.api.hooks.ListenerAdapter +import net.dv8tion.jda.api.requests.GatewayIntent +import net.dv8tion.jda.api.utils.cache.CacheFlag +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.ApplicationContext +import org.springframework.context.ApplicationEventPublisher +import org.springframework.context.PayloadApplicationEvent +import org.springframework.context.event.EventListener +import org.springframework.stereotype.Service + +@Service +@EnableConfigurationProperties(JdaConfiguration::class) +class JdaService( + applicationContext: ApplicationContext, + jdaConfiguration: JdaConfiguration, + publisher: ApplicationEventPublisher +) { + + private final val jda: JDA + private final val commands: Map + + init { + val requiredIntents: Set = + jdaConfiguration.cacheFlags + .mapNotNull(CacheFlag::getRequiredIntent) + .toSet() + + val builder = JDABuilder.createDefault(jdaConfiguration.token) + .setStatus(jdaConfiguration.onlineStatus) + .enableCache(jdaConfiguration.cacheFlags) + .enableIntents(requiredIntents) + if (jdaConfiguration.activity != null) { + builder.setActivity(Activity.playing(jdaConfiguration.activity!!)) + } + + jda = builder + .build() + .awaitReady() + .also { jda -> + jda.addEventListener(object : ListenerAdapter() { + override fun onGenericEvent(event: GenericEvent) { + publisher.publishEvent(PayloadApplicationEvent(jda, event)) + } + }) + } + + val contextCommands = applicationContext.getBeansOfType(Command::class.java).values + commands = contextCommands.associateBy { it.name } + + val commandDataList = contextCommands.map { it.toCommandData() } + + jda.updateCommands() + .addCommands(commandDataList) + .queue() + } + + @EventListener(SlashCommandInteractionEvent::class) + fun onSlashCommand(event: SlashCommandInteractionEvent) { + commands[event.name]?.let { command -> + runCatching { command.execute(event) } + .onFailure { e -> error("Error while executing command '${event.name}', $e") } + } + } + +} \ No newline at end of file