feat: added streak fix feature

This commit is contained in:
moonleay 2024-02-07 10:59:55 +01:00
parent 3133629b84
commit 00d16e657d
Signed by: moonleay
GPG key ID: 82667543CCD715FB
8 changed files with 411 additions and 23 deletions

View file

@ -20,16 +20,21 @@ package net.moonleay.bedge
import com.kotlindiscord.kord.extensions.ExtensibleBot import com.kotlindiscord.kord.extensions.ExtensibleBot
import dev.kord.common.entity.PresenceStatus import dev.kord.common.entity.PresenceStatus
import dev.kord.core.behavior.interaction.response.respond
import dev.kord.core.event.gateway.ReadyEvent import dev.kord.core.event.gateway.ReadyEvent
import dev.kord.core.event.interaction.ButtonInteractionCreateEvent
import dev.kord.core.on import dev.kord.core.on
import dev.kord.gateway.Intent import dev.kord.gateway.Intent
import dev.kord.gateway.PrivilegedIntent import dev.kord.gateway.PrivilegedIntent
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import net.moonleay.bedge.buttons.component.EditButtonManager
import net.moonleay.bedge.data.CredentialManager import net.moonleay.bedge.data.CredentialManager
import net.moonleay.bedge.data.database.DB import net.moonleay.bedge.data.database.DB
import net.moonleay.bedge.features.WakeupFeature import net.moonleay.bedge.features.WakeupFeature
import net.moonleay.bedge.util.Logger import net.moonleay.bedge.util.Logger
import net.moonleay.bedge.extensions.* import net.moonleay.bedge.extensions.*
import net.moonleay.bedge.util.EmbedColor
import net.moonleay.bedge.util.MessageUtil
import kotlin.system.exitProcess import kotlin.system.exitProcess
object Bot { object Bot {
@ -79,6 +84,7 @@ object Bot {
add(::AwakeExtension) add(::AwakeExtension)
add(::ProfileExtension) add(::ProfileExtension)
add(::TopExtension) add(::TopExtension)
add(::RequestStreakFix)
// add(::ShopExtension) // add(::ShopExtension)
} }
@ -98,6 +104,38 @@ object Bot {
} */ } */
} }
// Register button presses
bot.kordRef.on<ButtonInteractionCreateEvent> {
val inter = this.interaction
val u = inter.user
Logger.out("Button interaction: ${inter.componentId} from ${u.asUser().username}#${u.asUser().discriminator}")
if (inter.componentId.startsWith("public.edit.")) {
val response = inter.deferPublicMessageUpdate()
val g = this.interaction.getOriginalInteractionResponse().getGuild()
for (b in EditButtonManager.buttons) {
if (b.id != inter.componentId)
continue
b.onInteraction(inter, response, g, u)
return@on
}
return@on
}
if (inter.componentId.startsWith("public.message.")) {
val response = inter.deferPublicResponse()
response.respond {
this.embeds = mutableListOf(
MessageUtil.getEmbed(
EmbedColor.ERROR,
"404: Not Found",
"Could not find button with id \"${inter.componentId}\"." +
"\nPlease report this.",
u.asUser().username
)
)
}
}
}
bot.kordRef.on<ReadyEvent> { bot.kordRef.on<ReadyEvent> {
// run when init'd // run when init'd

View file

@ -0,0 +1,10 @@
package net.moonleay.bedge.buttons.component
import net.moonleay.bedge.buttons.streakfix.*
object EditButtonManager {
val buttons = listOf(
VouchEditButton(),
DeclineEditButton()
)
}

View file

@ -0,0 +1,19 @@
package net.moonleay.bedge.buttons.component
import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior
import dev.kord.core.entity.Guild
import dev.kord.core.entity.User
import dev.kord.core.entity.interaction.ButtonInteraction
interface IEditButton {
val id: String
suspend fun onInteraction(
interaction: ButtonInteraction,
response: PublicMessageInteractionResponseBehavior,
guild: Guild,
user: User
) {
}
}

View file

@ -0,0 +1,105 @@
package net.moonleay.bedge.buttons.streakfix
import dev.kord.common.entity.Snowflake
import dev.kord.core.behavior.edit
import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior
import dev.kord.core.entity.Guild
import dev.kord.core.entity.User
import dev.kord.core.entity.channel.MessageChannel
import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.EmbedBuilder
import dev.kord.rest.builder.message.modify.embed
import net.moonleay.bedge.Bot
import net.moonleay.bedge.buttons.component.IEditButton
import net.moonleay.bedge.data.database.repository.UserRepository
import net.moonleay.bedge.util.EmbedUtil
import net.moonleay.bedge.util.Logger
import net.moonleay.bedge.util.MessageUtil
class DeclineEditButton : IEditButton {
override val id: String = "public.edit.btn.streakfix.decline"
override suspend fun onInteraction(
interaction: ButtonInteraction,
response: PublicMessageInteractionResponseBehavior,
guild: Guild,
user: User
) {
val m = interaction.message
val eb = MessageUtil.getAClonedEmbed(m.embeds[0])
var shouldEditButton = false
if (!m.embeds[0].footer?.text?.endsWith("[ongoing]")!!){
Logger.out("This streakfix is not ongoing")
return
}
val member = interaction.user.asMember(guild.id)
// if (m.embeds[0].footer?.text?.contains(member.username)!!){
// Logger.out("cannot vote for own streakfix")
// return
// }
if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
// remove the user from the 1st list in the embed
Logger.out("Removing ${user.username} from the 1st list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 1).fields
shouldEditButton = true
}
if (!m.embeds[0].fields[1].value.contains(user.id.value.toString())) {
// Add the user to the list in the embed
Logger.out("Adding ${user.username} to the 2nd list in the embed")
eb.fields = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), eb, 2).fields
shouldEditButton = true
}
if (m.embeds[0].fields[1].value.contains(user.id.value.toString())) {
// Remove the user from all tables
Logger.out("Removing ${user.username} from the 2nd list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 2).fields
shouldEditButton = true
}
//Check if the vote is over
val vouchers = EmbedUtil.getAmountOfUsersInTableX(eb, 1)
val decliners = EmbedUtil.getAmountOfUsersInTableX(eb, 2)
Logger.out("Vouchers: $vouchers, Decliners: $decliners")
val target = m.embeds[0].footer?.text!!.split("{")[1].split("}")[0].toLong()
val targetData = UserRepository.getUserByID(target)!!
Logger.out("Target user = $target")
val canUpdate = targetData.isAwake && targetData.currentStreak == 0
val minvotes = 3
if (vouchers >= minvotes || decliners >= minvotes){
Logger.out("Voting is over")
eb.footer?.text = m.embeds[0].footer?.text?.replace("ongoing", "voting over").toString()
if (vouchers >= minvotes && canUpdate) {
Logger.out("Vouchers won")
val amountOfDays = m.embeds[0].author!!.name!!.split(": ")[1].toInt()
targetData.currentStreak = amountOfDays
if (targetData.longestStreak < amountOfDays)
targetData.longestStreak = amountOfDays
UserRepository.update(targetData)
eb.description += "\n**The vote was successful, the streak was fixed.**"
}
else {
Logger.out("Decliners won")
eb.description += "\n**The vote was unsuccessful, the streak was not fixed.**"
}
shouldEditButton = true
}
if (!canUpdate) {
eb.footer?.text = m.embeds[0].footer?.text?.replace("ongoing", "voting over").toString()
eb.description += "\n**The vote was canceled, because a new streak was started.**"
shouldEditButton = true
}
if (shouldEditButton) {
// update the message
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
this.embed(fun EmbedBuilder.() {
author = eb.author
color = eb.color
title = eb.title
description = eb.description
fields = eb.fields
footer = eb.footer
})
}
}
}
}

View file

@ -0,0 +1,107 @@
package net.moonleay.bedge.buttons.streakfix
import dev.kord.core.behavior.edit
import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior
import dev.kord.core.entity.Guild
import dev.kord.core.entity.User
import dev.kord.core.entity.channel.MessageChannel
import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.EmbedBuilder
import dev.kord.rest.builder.message.modify.embed
import net.moonleay.bedge.Bot
import net.moonleay.bedge.buttons.component.IEditButton
import net.moonleay.bedge.data.database.repository.UserRepository
import net.moonleay.bedge.util.EmbedUtil
import net.moonleay.bedge.util.Logger
import net.moonleay.bedge.util.MessageUtil
class VouchEditButton: IEditButton {
override val id: String = "public.edit.btn.streakfix.vouch"
override suspend fun onInteraction(
interaction: ButtonInteraction,
response: PublicMessageInteractionResponseBehavior,
guild: Guild,
user: User
) {
val m = interaction.message
val eb = MessageUtil.getAClonedEmbed(m.embeds[0])
var shouldEditButton = false
if (!m.embeds[0].footer?.text?.endsWith("[ongoing]")!!){
Logger.out("This streakfix is not ongoing")
return
}
val member = interaction.user.asMember(guild.id)
// if (m.embeds[0].footer?.text?.contains(member.username)!!){
// Logger.out("cannot vote for own streakfix")
// return
// }
// do the checks and update
if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
// remove the user from the 1st list in the embed
Logger.out("Removing ${user.username} from the 1st list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 1).fields
shouldEditButton = true
}
if (m.embeds[0].fields[1].value.contains(user.id.value.toString())) {
Logger.out("Removing ${user.username} from the 2nd list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 2).fields
shouldEditButton = true
}
if (!m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
//Add the user to the list in the embed
Logger.out("Adding ${user.username} to the 1st list in the embed")
eb.fields = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), eb, 1).fields
shouldEditButton = true
}
//Check if the vote is over
val vouchers = EmbedUtil.getAmountOfUsersInTableX(eb, 1)
val decliners = EmbedUtil.getAmountOfUsersInTableX(eb, 2)
Logger.out("Vouchers = $vouchers, Decliners = $decliners")
val target = m.embeds[0].footer?.text!!.split("{")[1].split("}")[0].toLong()
val targetData = UserRepository.getUserByID(target)!!
Logger.out("Target user = $target")
val canUpdate = targetData.isAwake && targetData.currentStreak == 0
val minvotes = 3
if ((vouchers >= minvotes || decliners >= minvotes) && canUpdate){
Logger.out("Voting is over")
eb.footer?.text = m.embeds[0].footer?.text?.replace("ongoing", "voting over").toString()
if (vouchers >= minvotes) {
Logger.out("Vouchers won")
val amountOfDays = m.embeds[0].author!!.name!!.split(": ")[1].toInt()
targetData.currentStreak = amountOfDays
if (targetData.longestStreak < amountOfDays)
targetData.longestStreak = amountOfDays
UserRepository.update(targetData)
eb.description += "\n**The vote was successful, the streak was fixed.**"
}
else {
Logger.out("Decliners won")
eb.description += "\n**The vote was unsuccessful, the streak was not fixed.**"
}
shouldEditButton = true
}
if (!canUpdate) {
eb.footer?.text = m.embeds[0].footer?.text?.replace("ongoing", "voting over").toString()
eb.description += "\n**The vote was canceled, because a new streak was started.**"
shouldEditButton = true
}
// Finish the update
if (shouldEditButton) {
// update the message
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
this.embed(fun EmbedBuilder.() {
author = eb.author
color = eb.color
title = eb.title
description = eb.description
fields = eb.fields
footer = eb.footer
author?.name = eb.author!!.name
})
}
}
}
}

View file

@ -0,0 +1,111 @@
package net.moonleay.bedge.extensions
import com.kotlindiscord.kord.extensions.commands.Arguments
import com.kotlindiscord.kord.extensions.commands.application.slash.converters.impl.numberChoice
import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import com.kotlindiscord.kord.extensions.types.respond
import dev.kord.core.behavior.interaction.followup.edit
import dev.kord.rest.builder.message.create.actionRow
import dev.kord.rest.builder.message.create.embed
import dev.kord.rest.builder.message.modify.embed
import net.moonleay.bedge.data.database.repository.UserRepository
import net.moonleay.bedge.util.*
class RequestStreakFix : Extension() {
override val name = "requeststreakfix"
override val allowApplicationCommandInDMs: Boolean
get() = false
override suspend fun setup() {
publicSlashCommand(::RequestStreakFixArguments) {
name = "requeststreakfix"
description = "Request a streak fix. This will be voted on. atleast 3 votes are needed to fix the streak."
this.action {
val target = this.user.asUser()
val wantedStreak = this.arguments.amountOfDays
if (!UserRepository.doesUserExist(target.id.value)) {
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
EmbedColor.ERROR,
"User not found!",
"You cant fix what ain't broken. You did not use the bot yet, so there is no information about you.",
target.username,
)
)
}
return@action
}
val tData = UserRepository.getUserByID(target.id.value)!!
if (!tData.isAwake) {
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
EmbedColor.ERROR,
"You are already asleep!",
"You can't fix a streak if you are already asleep.",
target.username,
)
)
}
return@action
}
if (tData.currentStreak != 0) {
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
EmbedColor.ERROR,
"Your streak is not broken!",
"You can't fix a streak if it is not broken.\n(Your current streak has to be 0.)",
target.username,
)
)
}
return@action
}
val eb = MessageUtil.getEmbedWithTable(
EmbedColor.INFO,
"Fix ${target.username}s streak",
"${target.mention} wants to fix their streak. Please vote on this request.\n" +
"The wanted streak is ${wantedStreak}.",
mapOf(
"Vouched" to listOf(),
"Declined" to listOf(),
)
)
val msg = this.respond {
this.content = "@everyone"
this.embed {
this.author {
this.name = "Requested days: $wantedStreak"
}
this.color = eb.color
this.title = eb.title
this.description = eb.description
this.fields = eb.fields
this.footer {
this.icon = target.avatar?.cdnUrl?.toUrl()
this.text = "requested by ${target.username} {${target.id.value}} [ongoing]"
}
}
this.actionRow {
this.components.addAll(EmbedUtil.getStreakFixButtons().components)
}
}
}
}
}
inner class RequestStreakFixArguments : Arguments() {
val amountOfDays by numberChoice {
this.name = "amountofdays"
this.description = "The desired amount of days for the streak."
}
}
}

View file

@ -24,32 +24,14 @@ import dev.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.EmbedBuilder import dev.kord.rest.builder.message.EmbedBuilder
object EmbedUtil { object EmbedUtil {
fun getTimePlannerButtons(): ActionRowBuilder { fun getStreakFixButtons(): ActionRowBuilder {
val ar = ActionRowBuilder() val ar = ActionRowBuilder()
ar.interactionButton(ButtonStyle.Success, "public.edit.btn.timemanagement.available") { ar.interactionButton(ButtonStyle.Success, "public.edit.btn.streakfix.vouch") {
this.label = "Available" this.label = "Vouch"
} }
ar.interactionButton(ButtonStyle.Primary, "public.edit.btn.timemanagement.maybeavailable") { ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.streakfix.decline") {
this.label = "May be available" this.label = "Decline"
} }
ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.timemanagement.notavailable") {
this.label = "Not available"
}
return ar
}
fun getMatchButtons(): ActionRowBuilder {
val ar = ActionRowBuilder()
ar.interactionButton(ButtonStyle.Success, "public.edit.btn.matchmanagement.accept") {
this.label = "I'm in!"
}
ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.matchmanagement.decline") {
this.label = "I'm out!"
}
/*
ar.interactionButton(ButtonStyle.Secondary, "public.edit.btn.matchmanagement.cancel") {
this.label = "Cancel this match..."
} */
return ar return ar
} }
@ -80,6 +62,13 @@ object EmbedUtil {
return ebbb return ebbb
} }
fun getAmountOfUsersInTableX(e: EmbedBuilder, table: Int): Int {
val f = e.fields[table - 1]
if (!f.value.contains("@"))
return 0
return f.value.split("\n").toMutableList().size
}
fun getAllUsersInTheFirstXTables(amountOfTables: Int, e: Embed): List<String> { fun getAllUsersInTheFirstXTables(amountOfTables: Int, e: Embed): List<String> {
val users = mutableListOf<String>() val users = mutableListOf<String>()
for (i in 0 until amountOfTables - 1) { for (i in 0 until amountOfTables - 1) {

View file

@ -75,6 +75,11 @@ object MessageUtil {
val ebb = EmbedBuilder() val ebb = EmbedBuilder()
ebb.color = e.color ebb.color = e.color
ebb.title = e.title ebb.title = e.title
ebb.author {
this.icon = e.author?.iconUrl
this.name = e.author?.name.toString()
this.url = e.author?.url
}
e.fields.forEach { e.fields.forEach {
val fb = EmbedBuilder.Field() val fb = EmbedBuilder.Field()
fb.name = it.name fb.name = it.name
@ -82,6 +87,10 @@ object MessageUtil {
fb.inline = it.inline fb.inline = it.inline
ebb.fields.add(fb) ebb.fields.add(fb)
} }
ebb.footer {
this.icon = e.footer?.iconUrl
this.text = e.footer?.text.toString()
}
ebb.description = e.description ebb.description = e.description
return ebb return ebb
} }