Skip to content

Commit f92b11a

Browse files
authored
Merge pull request #134 from the-programmers-hangout/develop
release: merge for 2.8.0
2 parents d513c8d + c601c5d commit f92b11a

File tree

9 files changed

+141
-22
lines changed

9 files changed

+141
-22
lines changed

commands.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,20 @@
5454
| rules | [Message] | List the rules of this guild. Pass a message ID to edit existing rules embed. |
5555

5656
## User
57-
| Commands | Arguments | Description |
58-
| ------------- | ----------------------------------------- | ---------------------------------------------------------- |
59-
| alts | User | Use this to view a user's alt accounts. |
60-
| ban | LowerUserArg, [Delete message days], Text | Ban a member from this guild. |
61-
| getBanReason | User | Get a ban reason for a banned user |
62-
| history, h, H | User | Use this to view a user's record. |
63-
| link | Main Account, Alt Account | Link a user's alt account with their main |
64-
| reset | LowerUserArg | Reset a user's record, and any linked accounts |
65-
| selfHistory | | View your infraction history (contents will be DM'd) |
66-
| setBanReason | User, Reason | Set a ban reason for a banned user |
67-
| unban | User | Unban a banned member from this guild. |
68-
| unlink | Main Account, Alt Account | Link a user's alt account with their main |
69-
| whatpfp | User | Perform a reverse image search of a User's profile picture |
57+
| Commands | Arguments | Description |
58+
| --------------- | ----------------------------------------- | --------------------------------------------------------------- |
59+
| alts | User | Use this to view a user's alt accounts. |
60+
| ban | LowerUserArg, [Delete message days], Text | Ban a member from this guild. |
61+
| deletedMessages | LowerUserArg | View a users messages deleted using the delete message reaction |
62+
| getBanReason | User | Get a ban reason for a banned user |
63+
| history, h, H | User | Use this to view a user's record. |
64+
| link | Main Account, Alt Account | Link a user's alt account with their main |
65+
| reset | LowerUserArg | Reset a user's record, and any linked accounts |
66+
| selfHistory | | View your infraction history (contents will be DM'd) |
67+
| setBanReason | User, Reason | Set a ban reason for a banned user |
68+
| unban | User | Unban a banned member from this guild. |
69+
| unlink | Main Account, Alt Account | Link a user's alt account with their main |
70+
| whatpfp | User | Perform a reverse image search of a User's profile picture |
7071

7172
## Utility
7273
| Commands | Arguments | Description |

src/main/kotlin/me/ddivad/judgebot/arguments/LowerMemberArg.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package me.ddivad.judgebot.arguments
22

33
import dev.kord.core.entity.Member
4+
import me.ddivad.judgebot.dataclasses.Configuration
45
import me.jakejmattson.discordkt.arguments.*
56
import me.jakejmattson.discordkt.commands.CommandEvent
67
import me.jakejmattson.discordkt.extensions.isSelf
@@ -15,14 +16,16 @@ open class LowerMemberArg(override val name: String = "LowerMemberArg") : Argume
1516

1617
override suspend fun convert(arg: String, args: List<String>, event: CommandEvent<*>): ArgumentResult<Member> {
1718
val guild = event.guild ?: return Error("No guild found")
19+
val configuration = event.discord.getInjectionObjects(Configuration :: class)
1820

1921
val member = arg.toSnowflakeOrNull()?.let { guild.getMemberOrNull(it) } ?: return Error("Not found")
2022
val author = event.author.asMember(event.guild!!.id)
2123

2224
return when {
2325
event.discord.permissions.isHigherLevel(event.discord, member, author) || event.author.isSelf() ->
2426
Error("You don't have the permission to use this command on the target user.")
25-
event.author == member -> Error("You can't use this command on yourself!")
27+
(event.author == member && member.id.toString() != configuration.ownerId) ->
28+
Error("You can't use this command on yourself!")
2629
else -> Success(member)
2730
}
2831
}

src/main/kotlin/me/ddivad/judgebot/arguments/LowerUserArg.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package me.ddivad.judgebot.arguments
22

33
import dev.kord.core.entity.User
4+
import me.ddivad.judgebot.dataclasses.Configuration
45
import me.jakejmattson.discordkt.arguments.*
56
import me.jakejmattson.discordkt.commands.CommandEvent
67
import me.jakejmattson.discordkt.extensions.isSelf
@@ -15,6 +16,7 @@ open class LowerUserArg(override val name: String = "LowerUserArg") : Argument<U
1516

1617
override suspend fun convert(arg: String, args: List<String>, event: CommandEvent<*>): ArgumentResult<User> {
1718
val guild = event.guild ?: return Error("No guild found")
19+
val configuration = event.discord.getInjectionObjects(Configuration :: class)
1820

1921
val user = arg.toSnowflakeOrNull()?.let { guild.kord.getUser(it) } ?: return Error("User Not Found")
2022
val member = guild.getMemberOrNull(user.id) ?: return Success(user)
@@ -23,7 +25,8 @@ open class LowerUserArg(override val name: String = "LowerUserArg") : Argument<U
2325
return when {
2426
event.discord.permissions.isHigherLevel(event.discord, member, author) || event.author.isSelf() ->
2527
Error("You don't have the permission to use this command on the target user.")
26-
event.author == member -> Error("You can't use this command on yourself!")
28+
(event.author == member && member.id.toString() != configuration.ownerId) ->
29+
Error("You can't use this command on yourself!")
2730
else -> Success(member.asUser())
2831
}
2932
}

src/main/kotlin/me/ddivad/judgebot/commands/UserCommands.kt

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package me.ddivad.judgebot.commands
22

33
import dev.kord.common.kColor
4+
import dev.kord.rest.Image
45
import dev.kord.x.emoji.Emojis
56
import dev.kord.x.emoji.addReaction
67
import kotlinx.coroutines.flow.toList
@@ -16,10 +17,9 @@ import me.ddivad.judgebot.services.LoggingService
1617
import me.ddivad.judgebot.services.infractions.BanService
1718
import me.jakejmattson.discordkt.arguments.*
1819
import me.jakejmattson.discordkt.commands.commands
19-
import me.jakejmattson.discordkt.extensions.mutualGuilds
20-
import me.jakejmattson.discordkt.extensions.pfpUrl
21-
import me.jakejmattson.discordkt.extensions.sendPrivateMessage
20+
import me.jakejmattson.discordkt.extensions.*
2221
import java.awt.Color
22+
import java.text.SimpleDateFormat
2323

2424
@Suppress("unused")
2525
fun createUserCommands(
@@ -195,4 +195,57 @@ fun createUserCommands(
195195
.startPublicly(discord, author, channel)
196196
}
197197
}
198+
199+
command("deletedMessages") {
200+
description = "View a users messages deleted using the delete message reaction"
201+
requiredPermission = Permissions.STAFF
202+
execute(LowerUserArg) {
203+
val target = args.first
204+
val guildMember = databaseService.users.getOrCreateUser(target, guild).getGuildInfo(guild.id.toString())
205+
val guildConfiguration = config[guild.asGuild().id.value]
206+
207+
val deletedMessages = databaseService.messageDeletes
208+
.getMessageDeletesForMember(guild.id.toString(), target.id.toString())
209+
.sortedByDescending { it.dateTime }
210+
.map { "Deleted on **${SimpleDateFormat("dd/MM/yyyy HH:mm").format(it.dateTime)}** \n[Message Link](${it.messageLink})" }
211+
.chunked(6)
212+
213+
respondMenu {
214+
deletedMessages.forEachIndexed { index, list ->
215+
page {
216+
color = discord.configuration.theme
217+
author {
218+
name = "Deleted messages for ${target.tag}"
219+
icon = target.pfpUrl
220+
}
221+
description = """
222+
**Showing messages deleted using ${guildConfiguration?.reactions?.deleteMessageReaction}**
223+
${target.tag} has **${guildMember.deletedMessageCount.deleteReaction}** deletions
224+
""".trimIndent()
225+
226+
list.forEach {
227+
field {
228+
value = it
229+
}
230+
}
231+
232+
footer {
233+
icon = guild.getIconUrl(Image.Format.PNG) ?: ""
234+
text = "${guild.name} | Page ${index + 1} of ${deletedMessages.size}"
235+
}
236+
}
237+
}
238+
if (deletedMessages.size > 1) {
239+
buttons {
240+
button("Prev.", Emojis.arrowLeft) {
241+
previousPage()
242+
}
243+
button("Next", Emojis.arrowRight) {
244+
nextPage()
245+
}
246+
}
247+
}
248+
}
249+
}
250+
}
198251
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package me.ddivad.judgebot.dataclasses
2+
3+
import java.util.Date
4+
5+
data class MessageDelete(
6+
val userId: String,
7+
val guildId: String,
8+
val messageLink: String?,
9+
val dateTime: Long = Date().time,
10+
)

src/main/kotlin/me/ddivad/judgebot/listeners/StaffReactionListeners.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import me.ddivad.judgebot.services.infractions.MuteService
1414
import me.ddivad.judgebot.services.infractions.RoleState
1515
import me.jakejmattson.discordkt.dsl.listeners
1616
import me.jakejmattson.discordkt.extensions.isSelf
17+
import me.jakejmattson.discordkt.extensions.jumpLink
1718
import me.jakejmattson.discordkt.extensions.sendPrivateMessage
1819

1920
@Suppress("unused")
@@ -30,8 +31,9 @@ fun onStaffReactionAdd(
3031
val staffMember = user.asMemberOrNull(guild.id) ?: return@on
3132
val msg = message.asMessage()
3233
val messageAuthor = msg.author?.asMemberOrNull(guild.id) ?: return@on
33-
if (discord.permissions.hasPermission(discord, staffMember, Permissions.MODERATOR)
34+
if ((discord.permissions.hasPermission(discord, staffMember, Permissions.MODERATOR)
3435
&& discord.permissions.isHigherLevel(discord, staffMember, messageAuthor)
36+
|| staffMember.id.toString() == configuration.ownerId)
3537
) {
3638
when (this.emoji.name) {
3739
guildConfiguration.reactions.gagReaction -> {
@@ -57,7 +59,7 @@ fun onStaffReactionAdd(
5759
loggingService.staffReactionUsed(guild, staffMember, messageAuthor, this.emoji)
5860
}
5961
guildConfiguration.reactions.deleteMessageReaction -> {
60-
msg.delete()
62+
message.delete()
6163
databaseService.users.addMessageDelete(
6264
guild,
6365
databaseService.users.getOrCreateUser(messageAuthor, guild.asGuild()),
@@ -73,7 +75,8 @@ fun onStaffReactionAdd(
7375
" Message deleted without notification."
7476
)
7577
}
76-
loggingService.staffReactionUsed(guild, staffMember, messageAuthor, this.emoji)
78+
val deleteLogMessage = loggingService.deleteReactionUsed(guild, staffMember, messageAuthor, this.emoji, msg)
79+
databaseService.messageDeletes.createMessageDeleteRecord(guildId.toString(), messageAuthor, deleteLogMessage.first()?.jumpLink())
7780
}
7881
Emojis.question.unicode -> {
7982
if (this.user.isSelf() || msg.author != this.message.kord.getSelf()) return@on

src/main/kotlin/me/ddivad/judgebot/services/DatabaseService.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package me.ddivad.judgebot.services
22

33
import me.ddivad.judgebot.services.database.GuildOperations
44
import me.ddivad.judgebot.services.database.JoinLeaveOperations
5+
import me.ddivad.judgebot.services.database.MessageDeleteOperations
56
import me.ddivad.judgebot.services.database.UserOperations
67
import me.jakejmattson.discordkt.annotations.Service
78

89
@Service
910
open class DatabaseService(
1011
val users: UserOperations,
1112
val guilds: GuildOperations,
12-
val joinLeaves: JoinLeaveOperations
13+
val joinLeaves: JoinLeaveOperations,
14+
val messageDeletes: MessageDeleteOperations
1315
)

src/main/kotlin/me/ddivad/judgebot/services/LoggingService.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,19 @@ class LoggingService(private val configuration: Configuration) {
7979
suspend fun staffReactionUsed(guild: Guild, moderator: User, target: Member, reaction: ReactionEmoji) =
8080
log(guild, "**Info ::** ${reaction.name} used by ${moderator.username} on ${target.mention}")
8181

82+
suspend fun deleteReactionUsed(guild: Guild, moderator: User, target: Member, reaction: ReactionEmoji, message: Message): List<Message?> {
83+
val msg = message.content.chunked(1800)
84+
val firstMessage = logAndReturnMessage(guild,
85+
"**Info ::** ${reaction.name} used by ${moderator.username} on ${target.mention}\n" +
86+
"**Message:**```\n" +
87+
"${msg.first()}\n```")
88+
89+
val rest = msg.takeLast(msg.size - 1).map {
90+
logAndReturnMessage(guild, "**Continued:**```\n$it\n```")}
91+
92+
return listOf(firstMessage).plus(rest)
93+
}
94+
8295
suspend fun pointDecayApplied(guild: Guild, target: GuildMember, newPoints: Int, pointsDeducted: Int, weeksSinceLastInfraction: Int) {
8396
val user = guild.kord.getUser(Snowflake(target.userId))
8497

@@ -95,6 +108,11 @@ class LoggingService(private val configuration: Configuration) {
95108
println("${SimpleDateFormat("dd/M/yyyy HH:mm:ss").format(Date())} > ${guild.name} > $message")
96109
}
97110

111+
private suspend fun logAndReturnMessage(guild: Guild, message: String): Message? {
112+
println("${SimpleDateFormat("dd/M/yyyy HH:mm:ss").format(Date())} > ${guild.name} > $message")
113+
return getLoggingChannel(guild)?.createMessage(message)
114+
}
115+
98116
private suspend fun getLoggingChannel(guild: Guild): TextChannel? {
99117
val channelId = configuration[guild.id.value]?.loggingConfiguration?.loggingChannel.takeIf { it!!.isNotEmpty() }
100118
?: return null
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package me.ddivad.judgebot.services.database
2+
3+
import dev.kord.core.entity.Member
4+
import me.ddivad.judgebot.dataclasses.MessageDelete
5+
import me.jakejmattson.discordkt.annotations.Service
6+
import org.litote.kmongo.and
7+
import org.litote.kmongo.eq
8+
9+
@Service
10+
class MessageDeleteOperations(connection: ConnectionService) {
11+
private val messageDeleteCollection = connection.db.getCollection<MessageDelete>("MessageDelete")
12+
13+
suspend fun createMessageDeleteRecord(guildId: String, target: Member, messageLink: String?) {
14+
val record = MessageDelete(target.id.toString(), guildId, messageLink)
15+
messageDeleteCollection.insertOne(record)
16+
}
17+
18+
suspend fun getMessageDeletesForMember(guildId: String, userId: String): List<MessageDelete> {
19+
return messageDeleteCollection.find(
20+
and(
21+
MessageDelete::guildId eq guildId,
22+
MessageDelete::userId eq userId,
23+
)
24+
).toList()
25+
}
26+
}

0 commit comments

Comments
 (0)