Skip to content

Commit

Permalink
refactor: rewrite on pure kord
Browse files Browse the repository at this point in the history
refactor: Build native image
  • Loading branch information
0ffz committed Dec 3, 2024
1 parent 4e9a915 commit 2263e93
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 268 deletions.
37 changes: 21 additions & 16 deletions .github/workflows/publish-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,40 @@ env:

jobs:
push:
name: "jib Docker build"
name: "Docker build"
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4

# - name: Set up QEMU for multi-platform support
# uses: docker/setup-qemu-action@v3

# - name: Set up Docker Buildx
# uses: docker/setup-buildx-action@v3
# with:
# buildkitd-flags: --debug

- name: Log in to the Container registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up JDK
uses: actions/setup-java@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- uses: graalvm/setup-graalvm@v1
with:
distribution: temurin
java-version: 21
java-version: '23'
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}
cache: gradle

- name: Publish image
run: gradle jib
- name: Run native compile
run: chmod +x gradlew && ./gradlew nativeCompile

- name: Build and push
uses: docker/build-push-action@v6
with:
file: Dockerfile
push: true
tags: MineInAbyss/discord-role-picker
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM alpine:latest
LABEL authors="offz"

RUN apk add gcompat

COPY build/native/nativeCompile/discord-role-picker /
ENTRYPOINT ["/discord-role-picker"]
68 changes: 23 additions & 45 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,74 +1,52 @@
plugins {
alias(libs.plugins.kotlinJvm)
alias(libs.plugins.kotlinx.serialization)
alias(libs.plugins.graalvm.nativeimage)
application
id("com.google.cloud.tools.jib") version "3.4.3"
id("com.ryandens.jlink-application") version "0.4.0"
}

repositories {
mavenCentral()
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://s01.oss.sonatype.org/content/repositories/snapshots")
}

dependencies {
implementation(libs.kordExtensions)
implementation(libs.kord)
implementation(libs.kotlinx.serialization.json)
implementation(libs.kaml)
implementation(libs.clikt)
implementation(libs.slf4j)
}

kotlin {
jvmToolchain(21)
jvmToolchain(23) // want this for graalvm 23 despite kotlin not supporting yet
}

application {
mainClass = "com.mineinabyss.discord.bot.MainKt"
java {
sourceCompatibility = JavaVersion.VERSION_22
targetCompatibility = JavaVersion.VERSION_22
}

tasks {
jibDockerBuild {
dependsOn("jlinkJre")
}
this.jib {
dependsOn("jlinkJre")
sourceSets {
main {
kotlin.srcDir("src")
}
}

jlinkJre {
modules.set(setOf("java.logging", "java.management", "jdk.crypto.ec", "java.naming")) // defaults to only java.base
application {
mainClass = "MainKt"
}

jib {
from.image = "gcr.io/distroless/java-base-debian11:nonroot-amd64"
to.image = "ghcr.io/mineinabyss/discord-role-picker"
extraDirectories {
paths {
path {
setFrom(file("build/jlink-jre/jre"))
into = "/usr/local"
}
}
permissions = mapOf("/usr/local/bin/java" to "755")
}
container {
environment = mapOf("BOT_CONFIG" to "/app/config.yml")
creationTime = "USE_CURRENT_TIMESTAMP"
ports = listOf("8080")
graalvmNative {
binaries {
named("main") {
fallback.set(false)
verbose.set(false)

// good defauls intended for Java 8 (>= 8u191) containers
jvmFlags = listOf(
"-server",
"-Djava.awt.headless=true",
"-XX:InitialRAMFraction=2",
"-XX:MinRAMFraction=2",
"-XX:MaxRAMFraction=2",
"-XX:+UseG1GC",
"-XX:MaxGCPauseMillis=100",
"-XX:+UseStringDeduplication"
)
buildArgs.addAll(
"--initialize-at-build-time",
"-Os"
)
imageName.set("discord-role-picker")
// runtimeArgs.add("-Xmx10m")
}
}
}

6 changes: 4 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
[versions]
clikt = "4.2.2"
kaml = "0.60.0"
kordExtensions = "1.8.1-SNAPSHOT"
kotlin = "2.0.0"
kotlinx-serialization = "1.7.0"
slf4j = "2.0.9"

[libraries]
clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" }
kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "kaml" }
kordExtensions = { module = "com.kotlindiscord.kord.extensions:kord-extensions", version.ref = "kordExtensions" }
#kordExtensions = "dev.kordex:kord-extensions:2.3.1-SNAPSHOT"
discord4j = "com.discord4j:discord4j-core:3.2.7"
kord = "dev.kord:kord-core:0.15.0"
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
slf4j = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }

[plugins]
kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
graalvm-nativeimage = "org.graalvm.buildtools.native:0.10.3"
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
3 changes: 2 additions & 1 deletion ...otlin/com/mineinabyss/discord/bot/Main.kt → src/Main.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
package com.mineinabyss.discord.bot
import bot.StartCommand


fun main(args: Array<String>) = StartCommand().main(args)
136 changes: 136 additions & 0 deletions src/bot/CreateButtons.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package bot

import config.Config
import config.RoleGroup
import dev.kord.common.entity.Permission
import dev.kord.common.entity.Permissions
import dev.kord.common.entity.Snowflake
import dev.kord.core.Kord
import dev.kord.core.behavior.edit
import dev.kord.core.behavior.interaction.respondEphemeral
import dev.kord.core.behavior.interaction.response.MessageInteractionResponseBehavior
import dev.kord.core.behavior.interaction.response.edit
import dev.kord.core.behavior.interaction.response.respond
import dev.kord.core.cache.data.toData
import dev.kord.core.entity.Message
import dev.kord.core.event.interaction.ButtonInteractionCreateEvent
import dev.kord.core.event.interaction.GuildChatInputCommandInteractionCreateEvent
import dev.kord.core.event.interaction.SelectMenuInteractionCreateEvent
import dev.kord.core.on
import dev.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.component.option
import dev.kord.rest.builder.message.actionRow
import java.util.concurrent.ConcurrentHashMap

class CreateButtons(
val kord: Kord,
val config: Config,
) {
private val pastResponses = ConcurrentHashMap<Snowflake, MessageInteractionResponseBehavior>()

suspend fun updateRolesMessage() {
if (config.rolesMessageReference == null) return
val message = Message(
kord.rest.channel.getMessage(
config.rolesMessageReference.channel,
config.rolesMessageReference.message
).toData(), kord
)
message.edit {
actionRow {
config.groups.forEach {
interactionButton(it.style, "roles/${it.id}") {
label = it.name
}
}
}
}
}

suspend fun init() {
val roleMessageCommand =
kord.createGuildChatInputCommand(config.guildId, "rolesmessage", "Create roles message") {
defaultMemberPermissions = Permissions(Permission.Administrator)
}

val rolesUpdateCommand =
kord.createGuildChatInputCommand(config.guildId, "rolesupdate", "Update roles message") {
defaultMemberPermissions = Permissions(Permission.Administrator)
}

kord.on<GuildChatInputCommandInteractionCreateEvent> {
println(interaction)
when (interaction.invokedCommandId) {
roleMessageCommand.id -> {
val response = interaction.deferEphemeralResponse()
interaction.channel.createMessage("Place this message's id into the config")
response.respond {
content = "Created roles message"
}
}

rolesUpdateCommand.id -> {
val response = interaction.deferEphemeralResponse()
updateRolesMessage()
response.respond { content = "Updated roles message" }
}
}
}

kord.on<SelectMenuInteractionCreateEvent> {
val comp = interaction.componentId
when {
comp.startsWith("select/") -> {
val response = interaction.deferEphemeralMessageUpdate()
val options = config.findByName(comp.removePrefix("select/"))?.options ?: return@on
val guild = kord.getGuild(config.guildId)
val member = guild.getMember(interaction.user.id)
val selectedRoles = interaction.values.filter { it != "unknown" }.map { Snowflake(it) }.toSet()
val (add, remove) = options.partition {
it.role in selectedRoles
}
add.forEach { member.addRole(it.role ?: return@forEach) }
remove.forEach { member.removeRole(it.role ?: return@forEach) }
response.edit {}
}
}
}

kord.on<ButtonInteractionCreateEvent> {
val comp = interaction.componentId
when {
comp.startsWith("roles/") -> {
val response = interaction.respondEphemeral {
pastResponses[interaction.user.id]?.delete()
actionRow {
createComponents(
this@on, config.findByName(comp.removePrefix("roles/")) ?: return@actionRow
)
}
}
pastResponses[interaction.user.id] = response
}
}
}
updateRolesMessage()
}

suspend inline fun ActionRowBuilder.createComponents(
event: ButtonInteractionCreateEvent,
group: RoleGroup,
) = stringSelect("select/${group.id}") {
val guild = kord.getGuild(config.guildId)
val member = guild.getMember(event.interaction.user.id)
val optionCount = group.options.count { option ->
val role = option.role?.let { guild.getRole(it) }
option(option.name ?: role?.name ?: "", role?.id?.toString() ?: return@count false) {
emoji = option.emoji
description = option.desc
default = member.roleIds.contains(role.id)
}
true
}
allowedValues = 0..optionCount
}
}

Loading

0 comments on commit 2263e93

Please sign in to comment.