Skip to content

Commit 67f5801

Browse files
committed
feat: migrate commands + move extensions
1 parent 228cb67 commit 67f5801

File tree

7 files changed

+186
-219
lines changed

7 files changed

+186
-219
lines changed

src/main/java/dev/qixils/quasicord/commands/ConfigCommand.kt

+33-46
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,37 @@
33
* License, v. 2.0. If a copy of the MPL was not distributed with this
44
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
*/
6-
7-
package dev.qixils.quasicord.commands;
8-
9-
import com.mongodb.client.model.ReplaceOptions;
10-
import dev.qixils.quasicord.Quasicord;
11-
import dev.qixils.quasicord.db.collection.LocaleConfig;
12-
import net.dv8tion.jda.api.entities.ISnowflake;
13-
import org.checkerframework.checker.nullness.qual.NonNull;
14-
import org.reactivestreams.Publisher;
15-
import reactor.core.publisher.Mono;
16-
17-
import java.util.Locale;
18-
19-
import static com.mongodb.client.model.Filters.and;
20-
import static com.mongodb.client.model.Filters.eq;
21-
22-
public abstract class ConfigCommand {
23-
24-
protected final @NonNull Quasicord library;
25-
26-
protected ConfigCommand(@NonNull Quasicord library) {
27-
this.library = library;
28-
}
29-
30-
protected Mono<?> setLocale(
31-
Locale locale,
32-
LocaleConfig.EntryType entryType,
33-
ISnowflake snowflake
34-
) {
35-
// TODO: handle diacritics
36-
// TODO: probably remove per-channel locale config i think
37-
38-
var collection = library.getDatabaseManager().collection(LocaleConfig.class);
39-
var filter = and(eq("entryType", entryType), eq("snowflake", snowflake.getIdLong()));
40-
Publisher<?> result;
41-
if (locale == null) {
42-
result = collection.deleteOne(filter);
43-
} else {
44-
result = collection.replaceOne(
45-
filter,
46-
new LocaleConfig(snowflake.getIdLong(), entryType, locale),
47-
new ReplaceOptions().upsert(true)
48-
);
49-
}
50-
return Mono.from(result);
51-
}
6+
package dev.qixils.quasicord.commands
7+
8+
import com.mongodb.client.model.Filters
9+
import com.mongodb.client.model.ReplaceOptions
10+
import dev.qixils.quasicord.Quasicord
11+
import dev.qixils.quasicord.db.collection.LocaleConfig
12+
import net.dv8tion.jda.api.entities.ISnowflake
13+
import java.util.*
14+
15+
abstract class ConfigCommand protected constructor(@JvmField protected val library: Quasicord) {
16+
protected suspend fun setLocale(
17+
locale: Locale?,
18+
entryType: LocaleConfig.EntryType,
19+
snowflake: ISnowflake
20+
) {
21+
// TODO: handle diacritics
22+
// TODO: probably remove per-channel locale config i think
23+
24+
val collection = library.databaseManager.collection<LocaleConfig>()
25+
val filter = Filters.and(
26+
Filters.eq("entryType", entryType),
27+
Filters.eq("snowflake", snowflake.idLong),
28+
)
29+
if (locale == null) {
30+
collection.deleteOne(filter)
31+
} else {
32+
collection.replaceOne(
33+
filter,
34+
LocaleConfig(snowflake.idLong, entryType, locale),
35+
ReplaceOptions().upsert(true)
36+
)
37+
}
38+
}
5239
}

src/main/java/dev/qixils/quasicord/commands/GuildConfigCommand.kt

+35-49
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,43 @@
33
* License, v. 2.0. If a copy of the MPL was not distributed with this
44
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
*/
6+
package dev.qixils.quasicord.commands
67

7-
package dev.qixils.quasicord.commands;
8-
9-
import dev.qixils.quasicord.Key;
10-
import dev.qixils.quasicord.Quasicord;
11-
import dev.qixils.quasicord.autocomplete.impl.LocaleAutoCompleter;
12-
import dev.qixils.quasicord.db.collection.LocaleConfig;
13-
import dev.qixils.quasicord.decorators.Namespace;
14-
import dev.qixils.quasicord.decorators.option.AutoCompleteWith;
15-
import dev.qixils.quasicord.decorators.option.Contextual;
16-
import dev.qixils.quasicord.decorators.option.Option;
17-
import dev.qixils.quasicord.decorators.slash.DefaultPermissions;
18-
import dev.qixils.quasicord.decorators.slash.SlashCommand;
19-
import dev.qixils.quasicord.decorators.slash.SlashSubCommand;
20-
import dev.qixils.quasicord.text.Text;
21-
import dev.qixils.quasicord.utils.QuasiMessage;
22-
import net.dv8tion.jda.api.Permission;
23-
import net.dv8tion.jda.api.entities.Guild;
24-
import net.dv8tion.jda.api.interactions.commands.OptionType;
25-
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
26-
import org.checkerframework.checker.nullness.qual.NonNull;
27-
import reactor.core.publisher.Mono;
28-
29-
import java.util.Locale;
8+
import dev.minn.jda.ktx.coroutines.await
9+
import dev.minn.jda.ktx.messages.reply_
10+
import dev.qixils.quasicord.Key.Companion.library
11+
import dev.qixils.quasicord.Quasicord
12+
import dev.qixils.quasicord.autocomplete.impl.LocaleAutoCompleter
13+
import dev.qixils.quasicord.db.collection.LocaleConfig
14+
import dev.qixils.quasicord.decorators.Namespace
15+
import dev.qixils.quasicord.decorators.option.AutoCompleteWith
16+
import dev.qixils.quasicord.decorators.option.Contextual
17+
import dev.qixils.quasicord.decorators.option.Option
18+
import dev.qixils.quasicord.decorators.slash.DefaultPermissions
19+
import dev.qixils.quasicord.decorators.slash.SlashCommand
20+
import dev.qixils.quasicord.decorators.slash.SlashSubCommand
21+
import dev.qixils.quasicord.locale.Context
22+
import net.dv8tion.jda.api.Permission
23+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
24+
import net.dv8tion.jda.api.interactions.commands.OptionType
25+
import java.util.*
3026

3127
@Namespace("quasicord")
3228
@SlashCommand(value = "server-config", guildOnly = true)
33-
@DefaultPermissions({Permission.MANAGE_SERVER})
34-
public class GuildConfigCommand extends ConfigCommand {
35-
36-
public GuildConfigCommand(@NonNull Quasicord library) {
37-
super(library);
38-
}
39-
40-
@SlashSubCommand("language")
41-
public Mono<QuasiMessage> setLocaleCommand(
42-
@Option(value = "language", type = OptionType.STRING)
43-
@AutoCompleteWith(LocaleAutoCompleter.class)
44-
Locale locale,
45-
@Contextual
46-
Guild guild
47-
) {
48-
return setLocale(locale, LocaleConfig.EntryType.GUILD, guild).map($ -> locale == null
49-
? Text.single(Key.library("guild-config.language.output.removed"))
50-
: Text.single(Key.library("guild-config.language.output.updated"), locale.getDisplayName(locale)))
51-
.map(text -> new QuasiMessage(text, request -> {
52-
if (request instanceof ReplyCallbackAction action) {
53-
//noinspection ResultOfMethodCallIgnored
54-
action.setEphemeral(true);
55-
}
56-
}));
57-
}
58-
29+
@DefaultPermissions(Permission.MANAGE_SERVER)
30+
class GuildConfigCommand(library: Quasicord) : ConfigCommand(library) {
31+
@SlashSubCommand("language")
32+
suspend fun setLocaleCommand(
33+
@Option(
34+
value = "language",
35+
type = OptionType.STRING
36+
) @AutoCompleteWith(LocaleAutoCompleter::class) locale: Locale?,
37+
@Contextual event: SlashCommandInteractionEvent,
38+
@Contextual ctx: Context,
39+
) {
40+
setLocale(locale, LocaleConfig.EntryType.GUILD, event.guild!!)
41+
val text = if (locale == null) ctx.text(library("guild-config.language.output.removed"))
42+
else ctx.text(library("guild-config.language.output.updated"), locale.getDisplayName(locale))
43+
event.reply_(text, ephemeral = true).await()
44+
}
5945
}

src/main/java/dev/qixils/quasicord/commands/UserConfigCommand.kt

+63-87
Original file line numberDiff line numberDiff line change
@@ -3,97 +3,73 @@
33
* License, v. 2.0. If a copy of the MPL was not distributed with this
44
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
*/
6+
package dev.qixils.quasicord.commands
67

7-
package dev.qixils.quasicord.commands;
8-
9-
import com.mongodb.client.model.ReplaceOptions;
10-
import dev.qixils.quasicord.Key;
11-
import dev.qixils.quasicord.Quasicord;
12-
import dev.qixils.quasicord.autocomplete.impl.LocaleAutoCompleter;
13-
import dev.qixils.quasicord.autocomplete.impl.TimeZoneAutoCompleter;
14-
import dev.qixils.quasicord.db.collection.LocaleConfig;
15-
import dev.qixils.quasicord.db.collection.TimeZoneConfig;
16-
import dev.qixils.quasicord.decorators.Namespace;
17-
import dev.qixils.quasicord.decorators.option.AutoCompleteWith;
18-
import dev.qixils.quasicord.decorators.option.Contextual;
19-
import dev.qixils.quasicord.decorators.option.Option;
20-
import dev.qixils.quasicord.decorators.slash.SlashCommand;
21-
import dev.qixils.quasicord.decorators.slash.SlashSubCommand;
22-
import dev.qixils.quasicord.text.Text;
23-
import dev.qixils.quasicord.utils.QuasiMessage;
24-
import net.dv8tion.jda.api.entities.User;
25-
import net.dv8tion.jda.api.entities.channel.Channel;
26-
import net.dv8tion.jda.api.entities.channel.ChannelType;
27-
import net.dv8tion.jda.api.interactions.commands.OptionType;
28-
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
29-
import org.reactivestreams.Publisher;
30-
import reactor.core.publisher.Mono;
31-
32-
import java.time.ZoneId;
33-
import java.util.Locale;
34-
35-
import static com.mongodb.client.model.Filters.eq;
8+
import com.mongodb.client.model.Filters
9+
import com.mongodb.client.model.ReplaceOptions
10+
import dev.minn.jda.ktx.coroutines.await
11+
import dev.minn.jda.ktx.messages.reply_
12+
import dev.qixils.quasicord.Key.Companion.library
13+
import dev.qixils.quasicord.Quasicord
14+
import dev.qixils.quasicord.autocomplete.impl.LocaleAutoCompleter
15+
import dev.qixils.quasicord.autocomplete.impl.TimeZoneAutoCompleter
16+
import dev.qixils.quasicord.db.collection.LocaleConfig
17+
import dev.qixils.quasicord.db.collection.TimeZoneConfig
18+
import dev.qixils.quasicord.decorators.Namespace
19+
import dev.qixils.quasicord.decorators.option.AutoCompleteWith
20+
import dev.qixils.quasicord.decorators.option.Contextual
21+
import dev.qixils.quasicord.decorators.option.Option
22+
import dev.qixils.quasicord.decorators.slash.SlashCommand
23+
import dev.qixils.quasicord.decorators.slash.SlashSubCommand
24+
import dev.qixils.quasicord.locale.Context
25+
import dev.qixils.quasicord.text.Text
26+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
27+
import net.dv8tion.jda.api.interactions.commands.OptionType
28+
import java.time.ZoneId
29+
import java.time.format.TextStyle
30+
import java.util.*
3631

3732
@Namespace("quasicord")
3833
@SlashCommand("user-config")
39-
public class UserConfigCommand extends ConfigCommand {
40-
41-
public UserConfigCommand(Quasicord library) {
42-
super(library);
43-
}
34+
class UserConfigCommand(library: Quasicord) : ConfigCommand(library) {
35+
@SlashSubCommand("language")
36+
suspend fun setLocaleCommand(
37+
@Option(
38+
value = "language",
39+
type = OptionType.STRING
40+
) @AutoCompleteWith(LocaleAutoCompleter::class) locale: Locale?,
41+
@Contextual event: SlashCommandInteractionEvent,
42+
@Contextual ctx: Context,
43+
) {
44+
setLocale(locale, LocaleConfig.EntryType.USER, event.user)
45+
val text = if (locale == null) ctx.text(library("user-config.language.output.removed"))
46+
else ctx.text(library("user-config.language.output.updated"), locale.getDisplayName(locale))
47+
event.reply_(text, ephemeral = event.isFromGuild).await()
48+
}
4449

45-
@SlashSubCommand("language")
46-
public Mono<QuasiMessage> setLocaleCommand(
47-
@Option(value = "language", type = OptionType.STRING)
48-
@AutoCompleteWith(LocaleAutoCompleter.class)
49-
Locale locale,
50-
@Contextual
51-
User user,
52-
@Contextual
53-
Channel channel
54-
) {
55-
return setLocale(locale, LocaleConfig.EntryType.USER, user).map($ -> locale == null
56-
? Text.single(Key.library("user-config.language.output.removed"))
57-
: Text.single(Key.library("user-config.language.output.updated"), locale.getDisplayName(locale)))
58-
.map(text -> new QuasiMessage(text, request -> {
59-
if (request instanceof ReplyCallbackAction action && channel.getType() != ChannelType.PRIVATE) {
60-
//noinspection ResultOfMethodCallIgnored
61-
action.setEphemeral(true);
62-
}
63-
}));
64-
}
50+
@SlashSubCommand("timezone")
51+
suspend fun setTimeZoneCommand(
52+
@Option(
53+
value = "timezone",
54+
type = OptionType.STRING
55+
) @AutoCompleteWith(TimeZoneAutoCompleter::class) tz: ZoneId?,
56+
@Contextual event: SlashCommandInteractionEvent,
57+
@Contextual ctx: Context,
58+
) {
59+
val collection = library.databaseManager.collection<TimeZoneConfig>()
60+
val filter = Filters.eq("snowflake", event.user.idLong)
61+
if (tz == null) {
62+
collection.deleteOne(filter)
63+
} else {
64+
collection.replaceOne(
65+
filter,
66+
TimeZoneConfig(event.user.idLong, tz),
67+
ReplaceOptions().upsert(true)
68+
)
69+
}
6570

66-
@SlashSubCommand("timezone")
67-
public Mono<QuasiMessage> setTimeZoneCommand(
68-
@Option(value = "timezone", type = OptionType.STRING)
69-
@AutoCompleteWith(TimeZoneAutoCompleter.class)
70-
ZoneId tz,
71-
@Contextual
72-
User user,
73-
@Contextual
74-
Channel channel
75-
) {
76-
var collection = library.getDatabaseManager().collection(TimeZoneConfig.class);
77-
var filter = eq("_id", user.getIdLong());
78-
Publisher<?> result;
79-
if (tz == null) {
80-
result = collection.deleteOne(filter);
81-
} else {
82-
result = collection.replaceOne(
83-
filter,
84-
new TimeZoneConfig(user.getIdLong(), tz),
85-
new ReplaceOptions().upsert(true)
86-
);
87-
}
88-
return Mono.empty(); // TODO
89-
// return Mono.from(result).map($ -> tz == null
90-
// ? Text.single(Key.library("user-config.timezone.output.removed"))
91-
// : Text.single(Key.library("user-config.timezone.output.updated"), (Text) locale -> tz.getDisplayName(TextStyle.FULL_STANDALONE, locale)))
92-
// .map(text -> new QuasiMessage(text, request -> {
93-
// if (request instanceof ReplyCallbackAction action && channel.getType() != ChannelType.PRIVATE) {
94-
// //noinspection ResultOfMethodCallIgnored
95-
// action.setEphemeral(true);
96-
// }
97-
// }));
98-
}
71+
val text = if (tz == null) ctx.text(library("user-config.timezone.output.removed"))
72+
else ctx.text(library("user-config.timezone.output.updated"), Text { locale -> tz.getDisplayName(TextStyle.FULL_STANDALONE, locale) })
73+
event.reply_(text, ephemeral = event.isFromGuild).await()
74+
}
9975
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package dev.qixils.quasicord.extensions
2+
3+
import dev.qixils.quasicord.locale.Context
4+
import net.dv8tion.jda.api.entities.Message
5+
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel
6+
import net.dv8tion.jda.api.interactions.Interaction
7+
8+
val Interaction.context: Context
9+
get() = Context.fromInteraction(this)
10+
11+
val Message.context: Context
12+
get() = Context.fromMessage(this)
13+
14+
val MessageChannel.context: Context
15+
get() = Context.fromChannel(this)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package dev.qixils.quasicord.extensions
2+
3+
import net.dv8tion.jda.api.Permission
4+
import net.dv8tion.jda.api.entities.Member
5+
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel
6+
import net.dv8tion.jda.internal.utils.Checks
7+
import net.dv8tion.jda.internal.utils.PermissionUtil
8+
9+
/**
10+
* Checks to see if the provided [Permissions][Permission] are available in a private channel.
11+
* @param permissions The [Permissions][Permission] being checked for.
12+
* @throws IllegalArgumentException if `permissions` is `null`
13+
* @return True if all the provided [Permissions][Permission] are available in a private channel
14+
*/
15+
@Throws(IllegalArgumentException::class)
16+
fun PermissionUtil.checkPrivateChannelPermission(vararg permissions: Permission?): Boolean {
17+
Checks.notNull(permissions, "permissions")
18+
19+
for (permission in permissions) {
20+
val canUse = when (permission) {
21+
Permission.VIEW_CHANNEL, Permission.MESSAGE_SEND, Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_ADD_REACTION, Permission.MESSAGE_ATTACH_FILES, Permission.MESSAGE_HISTORY, Permission.MESSAGE_EXT_EMOJI, Permission.MESSAGE_EXT_STICKER, Permission.VOICE_STREAM, Permission.VOICE_CONNECT, Permission.VOICE_SPEAK, Permission.VOICE_USE_VAD -> true
22+
else -> false
23+
}
24+
if (!canUse) return false
25+
}
26+
return true
27+
}
28+
29+
fun GuildChannel.botHas(vararg permissions: Permission) = PermissionUtil.checkPermission(permissionContainer, this.guild.selfMember, *permissions)
30+
31+
fun GuildChannel.memberHas(member: Member, vararg permissions: Permission) = PermissionUtil.checkPermission(permissionContainer, this.guild.selfMember, *permissions)

0 commit comments

Comments
 (0)