From c66b04067db8fd97bf74dd9e4da1db3a5743139e Mon Sep 17 00:00:00 2001 From: Gareth Coles Date: Wed, 2 Feb 2022 20:28:00 +0000 Subject: [PATCH] [#130, #132] Add convenience functions for editing members --- .../kord/extensions/annotations/DoNotChain.kt | 17 +++ .../kord/extensions/utils/_Member.kt | 106 +++++++++++++++++- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/annotations/DoNotChain.kt diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/annotations/DoNotChain.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/annotations/DoNotChain.kt new file mode 100644 index 0000000000..e2002c4483 --- /dev/null +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/annotations/DoNotChain.kt @@ -0,0 +1,17 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package com.kotlindiscord.kord.extensions.annotations + +/** Marks a class or function that's part of the bot builder DSLs. **/ +@RequiresOptIn( + message = "This function will cause an immediate REST call. If you want to do more than one operation here, " + + "you should use `.edit { }` instead as that will result in a single REST call for all operations - instead " + + "of a separate REST call for each operation.", + level = RequiresOptIn.Level.WARNING +) +@Target(AnnotationTarget.FUNCTION) +public annotation class DoNotChain diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/utils/_Member.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/utils/_Member.kt index 9dccb121c5..26ee4b9a66 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/utils/_Member.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/utils/_Member.kt @@ -6,14 +6,17 @@ package com.kotlindiscord.kord.extensions.utils +import com.kotlindiscord.kord.extensions.annotations.DoNotChain import dev.kord.common.entity.Permission import dev.kord.core.behavior.RoleBehavior +import dev.kord.core.behavior.edit import dev.kord.core.entity.Guild import dev.kord.core.entity.Member import dev.kord.core.entity.Role import dev.kord.rest.builder.member.MemberModifyBuilder import kotlinx.coroutines.flow.toList -import kotlinx.datetime.Instant +import kotlinx.datetime.* +import kotlin.time.Duration /** A more sensible name than `communicationDisabledUntil`. **/ public val Member.timeoutUntil: Instant? @@ -144,3 +147,104 @@ public suspend fun Member.canInteract(member: Member): Boolean { return highestRole.canInteract(otherHighestRole) } + +/** + * Convenience function to remove the timeout from a member, skipping the [edit] DSL. + */ +@DoNotChain +public suspend fun Member.removeTimeout(reason: String? = null): Member = + edit { + timeoutUntil = null + + this.reason = reason + } + +/** + * Convenience function to time out a member using a [Duration], skipping the [edit] DSL. + */ +@DoNotChain +public suspend fun Member.timeout(until: Duration, reason: String? = null): Member = + edit { + timeoutUntil = Clock.System.now() + until + + this.reason = reason + } + +/** + * Convenience function to time out a member using a [DateTimePeriod] and timezone, skipping the [edit] DSL. + * + * This will use [TimeZone.UTC] by default. You can provide another if you really need to. + */ +@DoNotChain +public suspend fun Member.timeout( + until: DateTimePeriod, + timezone: TimeZone = TimeZone.UTC, + reason: String? = null +): Member = + edit { + timeoutUntil = Clock.System.now().plus(until, timezone) + + this.reason = reason + } + +/** + * Convenience function to server mute a member, skipping the [edit] DSL. + */ +@DoNotChain +public suspend fun Member.mute(reason: String? = null): Member = edit { + muted = true + + this.reason = reason +} + +/** + * Convenience function to undo a server mute for a member, skipping the [edit] DSL. + */ +@DoNotChain +public suspend fun Member.unMute(reason: String? = null): Member = edit { + muted = false + + this.reason = reason +} + +/** + * Convenience function to server deafen a member, skipping the [edit] DSL. + */ +@DoNotChain +public suspend fun Member.deafen(reason: String? = null): Member = edit { + deafened = true + + this.reason = reason +} + +/** + * Convenience function to undo a server deafen for a member, skipping the [edit] DSL. + */ +@DoNotChain +public suspend fun Member.unDeafen(reason: String? = null): Member = edit { + deafened = false + + this.reason = reason +} + +/** + * Convenience function to set a member's nickname, skipping the [edit] DSL. + * + * You can also provide `null` to remove a nickname - [removeNickname] is a wrapper for this function that does + * exactly that. + */ +@DoNotChain +public suspend fun Member.setNickname(nickname: String?, reason: String? = null): Member = edit { + this.nickname = nickname + + this.reason = reason +} + +/** + * Convenience function to remove a member's nickname, skipping the [edit] DSL. + * + * This will simply call [setNickname] with a `nickname` of `null`. + */ +@DoNotChain +public suspend fun Member.removeNickname(reason: String? = null): Member = + setNickname(null, reason)