Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gh-101): allow admins to use most commands in DMs #102

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .releaserc.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
"path": "target/v-rising-discord-bot-*.jar",
"label": "v-rising-discord-bot-${nextRelease.version}.jar"
}
]
],
"successComment": false,
"releasedLabels": false
}
]
]
Expand Down
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ If you have questions or need support, feel free to join [this discord server](h

## Discord Commands

Please note that all commands are [guild](https://discord.com/developers/docs/resources/guild) specific.
Please note that all commands are [guild](https://discord.com/developers/docs/resources/guild) specific by default.

### `/list-servers`

Lists all server status monitors.
Admins can use this command in DMs, see [Configuration Properties](#configuration-properties) for details.

### `/add-server`

Expand All @@ -36,6 +37,7 @@ Adds a server to the status monitor.
### `/update-server`

Updates the given server status monitor. Only parameters specified are updated, all other parameters remain unchanged.
Admins can use this command in DMs, see [Configuration Properties](#configuration-properties) for details.

| Parameter | Description | Required | Default value |
|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|---------------|
Expand All @@ -53,6 +55,7 @@ Updates the given server status monitor. Only parameters specified are updated,
### `/remove-server`

Removes a server from the status monitor.
Admins can use this command in DMs, see [Configuration Properties](#configuration-properties) for details.

| Parameter | Description | Required | Default value |
|----------------------------|------------------------------------------------|----------|---------------|
Expand All @@ -61,24 +64,26 @@ Removes a server from the status monitor.
### `/get-server-details`

Gets all the configuration details for the specified server.
Admins can use this command in DMs, see [Configuration Properties](#configuration-properties) for details.

| Parameter | Description | Required | Default value |
|----------------------------|---------------------------------------------------------|----------|---------------|
| `server-status-monitor-id` | The id of the server status monitor to get details for. | `true` | `null` |

## Configuration Properties

| Property | Type | Description | Default value |
|----------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------|------------------------|
| `bot.discord-bot-token` | String | The token for the discord bot. You can find this in the [discord developer portal](https://discord.com/developers/applications). | `null` |
| `bot.database-path` | Path | The path to the database file. Should be overwritten when running inside a docker container. | `./bot.db` |
| `bot.database-username` | String | The username for the database. | `v-rising-discord-bot` |
| `bot.database-password` | String | The password for the database. | `null` |
| `bot.update-delay` | Duration | The delay between status monitor updates. At least 30 seconds. | `1m` |
| `bot.max-failed-attempts` | Int | The maximum number of attempts to be made until a server is disabled. Use `0` if you don't want to use this feature. | `0` |
| `bot.max-recent-errors` | Int | The maximum number of errors to keep for debugging via `/get-server-details`. Use `0` if you don't want to use this feature. | `5` |
| `bot.max-characters-per-error` | Int | The maximum number of errors to keep for debugging via `/get-server-details`. Use `0` if you don't want to use this feature. | `200` |
| `bot.allow-local-address-ranges` | Boolean | Whether or not addresses from reserved ip ranges are permitted when adding or updating status monitors. | `true` |
| Property | Type | Description | Default value |
|----------------------------------|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|
| `bot.discord-bot-token` | String | The token for the discord bot. You can find this in the [discord developer portal](https://discord.com/developers/applications). | `null` |
| `bot.database-path` | Path | The path to the database file. Should be overwritten when running inside a docker container. | `./bot.db` |
| `bot.database-username` | String | The username for the database. | `v-rising-discord-bot` |
| `bot.database-password` | String | The password for the database. | `null` |
| `bot.update-delay` | Duration | The delay between status monitor updates. At least 30 seconds. | `1m` |
| `bot.max-failed-attempts` | Int | The maximum number of attempts to be made until a server is disabled. Use `0` if you don't want to use this feature. | `0` |
| `bot.max-recent-errors` | Int | The maximum number of errors to keep for debugging via `/get-server-details`. Use `0` if you don't want to use this feature. | `5` |
| `bot.max-characters-per-error` | Int | The maximum number of errors to keep for debugging via `/get-server-details`. Use `0` if you don't want to use this feature. | `200` |
| `bot.allow-local-address-ranges` | Boolean | Whether or not addresses from reserved ip ranges are permitted when adding or updating status monitors. | `true` |
| `bot.admin-user-ids` | Set<String> | A list of admin user ids. Admins are allowed to DM the bot directly to issue commands. Commands are no longer guild specific in this context. For example, if an admin uses the `/list-servers` command in a DM, the bot responds with a list of all server status monitors and not only the ones for a specific discord guild. | `emptySet()` |

## [v-rising-discord-bot-companion](https://github.com/DarkAtra/v-rising-discord-bot-companion) Integration

Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
</compilerPlugins>
<args>
<arg>-Xjsr305=strict</arg>
<arg>-Xemit-jvm-type-annotations</arg>
</args>
</configuration>
<dependencies>
Expand Down
11 changes: 10 additions & 1 deletion src/main/kotlin/de/darkatra/vrising/discord/Bot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.isActive
import kotlinx.coroutines.runBlocking
import org.dizitart.no2.Nitrite
import org.slf4j.LoggerFactory
import org.springframework.aot.hint.annotation.RegisterReflectionForBinding
import org.springframework.beans.factory.DisposableBean
import org.springframework.boot.ApplicationArguments
Expand Down Expand Up @@ -52,6 +53,8 @@ class Bot(
private val serverStatusMonitorService: ServerStatusMonitorService
) : ApplicationRunner, DisposableBean, SchedulingConfigurer {

private val logger = LoggerFactory.getLogger(javaClass)

private var isReady = AtomicBoolean(false)
private lateinit var kord: Kord

Expand All @@ -65,7 +68,7 @@ class Bot(

kord.on<ChatInputCommandInteractionCreateEvent> {

val command = commands.find { command -> command.isSupported(interaction) }
val command = commands.find { command -> command.isSupported(interaction, botProperties.adminUserIds) }
if (command == null) {
interaction.deferEphemeralResponse().respond {
content = """This command is not supported here, please refer to the documentation.
Expand All @@ -77,9 +80,15 @@ class Bot(
try {
command.handle(interaction)
} catch (e: BotException) {
logger.error("Could not perform command '${command.getCommandName()}'.", e)
interaction.deferEphemeralResponse().respond {
content = "Could not perform command. Cause: ${e.message}"
}
} catch (t: Throwable) {
logger.error("An unexpected error occurred.", t)
interaction.deferEphemeralResponse().respond {
content = "An unexpected error occurred."
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/de/darkatra/vrising/discord/BotProperties.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ class BotProperties {
@field:NotNull
var maxCharactersPerError: Int = 200

@field:NotNull
var allowLocalAddressRanges: Boolean = true

@field:NotNull
var adminUserIds: Set<@NotBlank String> = emptySet()
}
11 changes: 4 additions & 7 deletions src/main/kotlin/de/darkatra/vrising/discord/DatabaseUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ package de.darkatra.vrising.discord
import org.dizitart.kno2.filters.and
import org.dizitart.no2.objects.ObjectFilter

operator fun ObjectFilter?.plus(other: ObjectFilter?): ObjectFilter? {
if (this == null && other == null) {
return null
operator fun ObjectFilter.plus(other: ObjectFilter?): ObjectFilter {
if (other == null) {
return this
}
if (this != null && other != null) {
return this.and(other)
}
return this ?: other
return this.and(other)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import de.darkatra.vrising.discord.serverstatus.model.ServerStatusMonitorStatus
import dev.kord.core.Kord
import dev.kord.core.behavior.interaction.response.respond
import dev.kord.core.entity.interaction.ChatInputCommandInteraction
import dev.kord.core.entity.interaction.GlobalChatInputCommandInteraction
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
import org.slf4j.LoggerFactory
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.stereotype.Component

Expand All @@ -37,6 +39,8 @@ class AddServerCommand(
private val botProperties: BotProperties
) : Command {

private val logger = LoggerFactory.getLogger(javaClass)

private val name: String = "add-server"
private val description: String = "Adds a server to the status monitor."

Expand Down Expand Up @@ -65,6 +69,13 @@ class AddServerCommand(
}
}

override fun isSupported(interaction: ChatInputCommandInteraction, adminUserIds: Set<String>): Boolean {
if (interaction is GlobalChatInputCommandInteraction) {
return false
}
return super.isSupported(interaction, adminUserIds)
}

override suspend fun handle(interaction: ChatInputCommandInteraction) {

val hostname = interaction.getServerHostnameParameter()!!
Expand Down Expand Up @@ -102,6 +113,8 @@ class AddServerCommand(
)
)

logger.info("Successfully added monitor with id '${serverStatusMonitorId}' for '${hostname}:${queryPort}' to channel '$channelId'.")

interaction.deferEphemeralResponse().respond {
content = """Added monitor with id '${serverStatusMonitorId}' for '${hostname}:${queryPort}' to channel '$channelId'.
|It may take some time until the status message appears.""".trimMargin()
Expand Down
13 changes: 11 additions & 2 deletions src/main/kotlin/de/darkatra/vrising/discord/commands/Command.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package de.darkatra.vrising.discord.commands

import dev.kord.core.Kord
import dev.kord.core.entity.interaction.ChatInputCommandInteraction
import dev.kord.core.entity.interaction.GlobalChatInputCommandInteraction
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction

interface Command {
Expand All @@ -10,8 +11,16 @@ interface Command {

suspend fun register(kord: Kord)

fun isSupported(interaction: ChatInputCommandInteraction): Boolean {
return interaction.invokedCommandName == getCommandName() && !interaction.user.isBot && interaction is GuildChatInputCommandInteraction
fun isSupported(interaction: ChatInputCommandInteraction, adminUserIds: Set<String>): Boolean {

if (interaction.invokedCommandName != getCommandName() || interaction.user.isBot) {
return false
}

return when (interaction) {
is GuildChatInputCommandInteraction -> true
is GlobalChatInputCommandInteraction -> adminUserIds.contains(interaction.user.id.toString())
}
}

suspend fun handle(interaction: ChatInputCommandInteraction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import de.darkatra.vrising.discord.serverstatus.ServerStatusMonitorRepository
import dev.kord.core.Kord
import dev.kord.core.behavior.interaction.response.respond
import dev.kord.core.entity.interaction.ChatInputCommandInteraction
import dev.kord.core.entity.interaction.GlobalChatInputCommandInteraction
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
import dev.kord.rest.builder.message.modify.embed
import org.springframework.boot.context.properties.EnableConfigurationProperties
Expand All @@ -31,7 +32,7 @@ class GetServerDetailsCommand(
name = name,
description = description
) {
dmPermission = false
dmPermission = true
disableCommandInGuilds()

addServerStatusMonitorIdParameter()
Expand All @@ -41,9 +42,12 @@ class GetServerDetailsCommand(
override suspend fun handle(interaction: ChatInputCommandInteraction) {

val serverStatusMonitorId = interaction.getServerStatusMonitorIdParameter()
val discordServerId = (interaction as GuildChatInputCommandInteraction).guildId

val serverStatusMonitor = serverStatusMonitorRepository.getServerStatusMonitor(serverStatusMonitorId, discordServerId.toString())
val serverStatusMonitor = when (interaction) {
is GuildChatInputCommandInteraction -> serverStatusMonitorRepository.getServerStatusMonitor(serverStatusMonitorId, interaction.guildId.toString())
is GlobalChatInputCommandInteraction -> serverStatusMonitorRepository.getServerStatusMonitor(serverStatusMonitorId)
}

if (serverStatusMonitor == null) {
interaction.deferEphemeralResponse().respond {
content = "No server with id '$serverStatusMonitorId' was found."
Expand Down
Loading
Loading