Compare commits
6 commits
883940c8fd
...
d97511eb8b
Author | SHA1 | Date | |
---|---|---|---|
d97511eb8b | |||
63fb1c0c8f | |||
308da65105 | |||
9400a21403 | |||
f7b701de20 | |||
165e1d342c |
8 changed files with 295 additions and 112 deletions
|
@ -32,7 +32,7 @@ val ownerID = 372703841151614976L
|
|||
group = "net.moonleay.liljudd"
|
||||
version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" }
|
||||
?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" }
|
||||
?: "2.4.3"
|
||||
?: "2.5.0"
|
||||
|
||||
val kordver = "1.5.6"
|
||||
val coroutinesver = "1.1.0"
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
|
||||
package net.moonleay.lilJudd.buttons.component
|
||||
|
||||
import net.moonleay.lilJudd.buttons.matchplanner.AcceptEditButton
|
||||
import net.moonleay.lilJudd.buttons.matchplanner.CancelEditButton
|
||||
import net.moonleay.lilJudd.buttons.matchplanner.SignMeUpEditButton
|
||||
import net.moonleay.lilJudd.buttons.matchplanner.DeclineEditButton
|
||||
import net.moonleay.lilJudd.buttons.timeplanner.IsAvailableEditButton
|
||||
import net.moonleay.lilJudd.buttons.timeplanner.MaybeAvailableEditButton
|
||||
import net.moonleay.lilJudd.buttons.timeplanner.NotAvailableEditButton
|
||||
|
@ -29,7 +30,8 @@ object EditButtonManager {
|
|||
IsAvailableEditButton(),
|
||||
MaybeAvailableEditButton(),
|
||||
NotAvailableEditButton(),
|
||||
SignMeUpEditButton(),
|
||||
CancelEditButton()
|
||||
AcceptEditButton(),
|
||||
CancelEditButton(),
|
||||
DeclineEditButton(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* lilJudd
|
||||
* Copyright (C) 2023 moonleay
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.moonleay.lilJudd.buttons.matchplanner
|
||||
|
||||
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.modify.embed
|
||||
import net.moonleay.lilJudd.Bot
|
||||
import net.moonleay.lilJudd.buttons.component.IEditButton
|
||||
import net.moonleay.lilJudd.data.entry.MatchPlanningDataData
|
||||
import net.moonleay.lilJudd.data.tables.MatchPlanningData
|
||||
import net.moonleay.lilJudd.util.EmbedUtil
|
||||
import net.moonleay.lilJudd.util.Logger
|
||||
import net.moonleay.lilJudd.util.MessageUtil
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class AcceptEditButton() : IEditButton {
|
||||
override val id: String = "public.edit.btn.matchmanagement.accept"
|
||||
|
||||
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
|
||||
lateinit var mpdd: MatchPlanningDataData
|
||||
var found = false
|
||||
transaction {
|
||||
for (pnr in MatchPlanningData.select {
|
||||
MatchPlanningData.messageid eq (interaction.message.id.value.toString()) and (
|
||||
MatchPlanningData.serverid eq (guild.id.value.toString())) and (
|
||||
MatchPlanningData.channelid eq (interaction.channelId.value.toString()))
|
||||
}) {
|
||||
mpdd = MatchPlanningDataData(
|
||||
pnr[MatchPlanningData.id].value,
|
||||
pnr[MatchPlanningData.serverid],
|
||||
pnr[MatchPlanningData.channelid],
|
||||
pnr[MatchPlanningData.matchtype],
|
||||
pnr[MatchPlanningData.registererid],
|
||||
pnr[MatchPlanningData.roleid],
|
||||
pnr[MatchPlanningData.opponentName],
|
||||
pnr[MatchPlanningData.messageid],
|
||||
pnr[MatchPlanningData.timestamp],
|
||||
pnr[MatchPlanningData.jobstr]
|
||||
)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (!found || mpdd == null) {
|
||||
return
|
||||
}
|
||||
val role = guild.getRoleOrNull(Snowflake(mpdd.roleid)) ?: return
|
||||
val member = interaction.user.asMember(guild.id) ?: return
|
||||
// do the checks and update
|
||||
if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
|
||||
if (member.roleIds.contains(Snowflake(mpdd.roleid))) {
|
||||
Logger.out("Removing role from ${member.username}")
|
||||
member.removeRole(role.id)
|
||||
}
|
||||
// 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())) {
|
||||
if (!member.roleIds.contains(Snowflake(mpdd.roleid))) {
|
||||
Logger.out("Adding role to ${member.username}")
|
||||
member.addRole(role.id)
|
||||
}
|
||||
//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
|
||||
}
|
||||
if (shouldEditButton) {
|
||||
// update the message
|
||||
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
|
||||
this.embed {
|
||||
this.color = eb.color
|
||||
this.title = eb.title
|
||||
this.description = eb.description
|
||||
this.fields = eb.fields
|
||||
this.footer = eb.footer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* lilJudd
|
||||
* Copyright (C) 2023 moonleay
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.moonleay.lilJudd.buttons.matchplanner
|
||||
|
||||
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.modify.embed
|
||||
import net.moonleay.lilJudd.Bot
|
||||
import net.moonleay.lilJudd.buttons.component.IEditButton
|
||||
import net.moonleay.lilJudd.data.entry.MatchPlanningDataData
|
||||
import net.moonleay.lilJudd.data.tables.MatchPlanningData
|
||||
import net.moonleay.lilJudd.util.EmbedUtil
|
||||
import net.moonleay.lilJudd.util.Logger
|
||||
import net.moonleay.lilJudd.util.MessageUtil
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class DeclineEditButton : IEditButton {
|
||||
override val id: String = "public.edit.btn.matchmanagement.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
|
||||
lateinit var mpdd: MatchPlanningDataData
|
||||
var found = false
|
||||
transaction {
|
||||
for (pnr in MatchPlanningData.select {
|
||||
MatchPlanningData.messageid eq (interaction.message.id.value.toString()) and (
|
||||
MatchPlanningData.serverid eq (guild.id.value.toString())) and (
|
||||
MatchPlanningData.channelid eq (interaction.channelId.value.toString()))
|
||||
}) {
|
||||
mpdd = MatchPlanningDataData(
|
||||
pnr[MatchPlanningData.id].value,
|
||||
pnr[MatchPlanningData.serverid],
|
||||
pnr[MatchPlanningData.channelid],
|
||||
pnr[MatchPlanningData.matchtype],
|
||||
pnr[MatchPlanningData.registererid],
|
||||
pnr[MatchPlanningData.roleid],
|
||||
pnr[MatchPlanningData.opponentName],
|
||||
pnr[MatchPlanningData.messageid],
|
||||
pnr[MatchPlanningData.timestamp],
|
||||
pnr[MatchPlanningData.jobstr]
|
||||
)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (!found || mpdd == null) {
|
||||
return
|
||||
}
|
||||
val role = guild.getRoleOrNull(Snowflake(mpdd.roleid)) ?: return
|
||||
val member = interaction.user.asMember(guild.id) ?: return
|
||||
if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
|
||||
if (member.roleIds.contains(Snowflake(mpdd.roleid))) {
|
||||
Logger.out("Removing role from ${member.username}")
|
||||
member.removeRole(role.id)
|
||||
}
|
||||
// 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())) {
|
||||
if (member.roleIds.contains(Snowflake(mpdd.roleid))) {
|
||||
Logger.out("Removing role from ${member.username}")
|
||||
member.removeRole(role.id)
|
||||
}
|
||||
// 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
|
||||
}
|
||||
if (shouldEditButton) {
|
||||
// update the message
|
||||
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
|
||||
this.embed {
|
||||
this.color = eb.color
|
||||
this.title = eb.title
|
||||
this.description = eb.description
|
||||
this.fields = eb.fields
|
||||
this.footer = eb.footer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* lilJudd
|
||||
* Copyright (C) 2023 moonleay
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.moonleay.lilJudd.buttons.matchplanner
|
||||
|
||||
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.modify.embed
|
||||
import net.moonleay.lilJudd.Bot
|
||||
import net.moonleay.lilJudd.buttons.component.IEditButton
|
||||
import net.moonleay.lilJudd.data.entry.MatchPlanningDataData
|
||||
import net.moonleay.lilJudd.data.tables.MatchPlanningData
|
||||
import net.moonleay.lilJudd.util.EmbedUtil
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class SignMeUpEditButton() : IEditButton {
|
||||
override val id: String = "public.edit.btn.matchmanagement.accept"
|
||||
|
||||
override suspend fun onInteraction(
|
||||
interaction: ButtonInteraction,
|
||||
response: PublicMessageInteractionResponseBehavior,
|
||||
guild: Guild,
|
||||
user: User
|
||||
) {
|
||||
val m = interaction.message
|
||||
if (!m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
|
||||
lateinit var mpdd: MatchPlanningDataData
|
||||
var found = false
|
||||
transaction {
|
||||
for (pnr in MatchPlanningData.select {
|
||||
MatchPlanningData.messageid eq (interaction.message.id.value.toString()) and (
|
||||
MatchPlanningData.serverid eq (guild.id.value.toString())) and (
|
||||
MatchPlanningData.channelid eq (interaction.channelId.value.toString()))
|
||||
}) {
|
||||
mpdd = MatchPlanningDataData(
|
||||
pnr[MatchPlanningData.id].value,
|
||||
pnr[MatchPlanningData.serverid],
|
||||
pnr[MatchPlanningData.channelid],
|
||||
pnr[MatchPlanningData.matchtype],
|
||||
pnr[MatchPlanningData.registererid],
|
||||
pnr[MatchPlanningData.roleid],
|
||||
pnr[MatchPlanningData.opponentName],
|
||||
pnr[MatchPlanningData.messageid],
|
||||
pnr[MatchPlanningData.timestamp],
|
||||
pnr[MatchPlanningData.jobstr]
|
||||
)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (!found || mpdd == null) {
|
||||
return
|
||||
}
|
||||
val role = guild.getRoleOrNull(Snowflake(mpdd.roleid)) ?: return
|
||||
val member = interaction.user.asMember(guild.id)
|
||||
if (!member.roleIds.contains(Snowflake(mpdd.roleid))) {
|
||||
member.addRole(role.id)
|
||||
}
|
||||
|
||||
//Add the user to the list in the embed
|
||||
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
|
||||
this.embed {
|
||||
val temp = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), m.embeds[0], 1)
|
||||
this.color = temp.color
|
||||
this.title = temp.title
|
||||
this.description = temp.description
|
||||
this.fields = temp.fields
|
||||
this.footer = temp.footer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -67,6 +67,7 @@ class MatchExtension : Extension() {
|
|||
"Registered by ${m.mention}",
|
||||
mapOf(
|
||||
"Signed up" to listOf(),
|
||||
"Unavailable" to listOf(),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -120,7 +121,7 @@ class MatchExtension : Extension() {
|
|||
MatchJob(
|
||||
jobString,
|
||||
tableID.value,
|
||||
"${args.matchType.readableName}_Vs_${opponent}_[${tableID.value}]-${gID}_${cID}"
|
||||
"${args.matchType.readableName}_Vs_${opponent}_[${tableID.value}]-${gID}_${cID}",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -41,17 +41,26 @@ object EmbedUtil {
|
|||
fun getMatchButtons(): ActionRowBuilder {
|
||||
val ar = ActionRowBuilder()
|
||||
ar.interactionButton(ButtonStyle.Success, "public.edit.btn.matchmanagement.accept") {
|
||||
this.label = "Sign me up!"
|
||||
this.label = "I'm in!"
|
||||
}
|
||||
ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.matchmanagement.cancel") {
|
||||
this.label = "Cancel"
|
||||
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
|
||||
}
|
||||
|
||||
fun replaceXWithYinValuesAtTable(x: String, y: String, e: Embed, table: Int): EmbedBuilder {
|
||||
val ebb = MessageUtil.getAClonedEmbedd(e)
|
||||
for ((i, f) in e.fields.withIndex()) {
|
||||
return replaceXWithYinValuesAtTable(x, y, MessageUtil.getAClonedEmbed(e), table)
|
||||
}
|
||||
|
||||
fun replaceXWithYinValuesAtTable(x: String, y: String, ebb: EmbedBuilder, table: Int): EmbedBuilder {
|
||||
val ebbb = MessageUtil.getAClonedEmbed(ebb)
|
||||
ebbb.fields = mutableListOf()
|
||||
for ((i, f) in ebb.fields.withIndex()) {
|
||||
val fb = EmbedBuilder.Field()
|
||||
fb.name = f.name
|
||||
if (i == table - 1) {
|
||||
|
@ -66,9 +75,9 @@ object EmbedUtil {
|
|||
} else
|
||||
fb.value = f.value
|
||||
fb.inline = true
|
||||
ebb.fields.add(fb)
|
||||
ebbb.fields.add(fb)
|
||||
}
|
||||
return ebb
|
||||
return ebbb
|
||||
}
|
||||
|
||||
fun getAllUsersInTheFirstXTables(amountOfTables: Int, e: Embed): List<String> {
|
||||
|
@ -87,8 +96,13 @@ object EmbedUtil {
|
|||
}
|
||||
|
||||
fun addXToValuesAtTable(x: String, e: Embed, table: Int): EmbedBuilder {
|
||||
val ebb = MessageUtil.getAClonedEmbedd(e)
|
||||
for ((i, f) in e.fields.withIndex()) {
|
||||
return addXToValuesAtTable(x, MessageUtil.getAClonedEmbed(e), table)
|
||||
}
|
||||
|
||||
fun addXToValuesAtTable(x: String, ebb: EmbedBuilder, table: Int): EmbedBuilder {
|
||||
val ebbb = MessageUtil.getAClonedEmbed(ebb)
|
||||
ebbb.fields = mutableListOf()
|
||||
ebb.fields.forEachIndexed { i, f ->
|
||||
val fb = EmbedBuilder.Field()
|
||||
fb.name = f.name
|
||||
if (i == table - 1)
|
||||
|
@ -105,9 +119,9 @@ object EmbedUtil {
|
|||
}
|
||||
|
||||
fb.inline = true
|
||||
ebb.fields.add(fb)
|
||||
ebbb.fields.add(fb)
|
||||
}
|
||||
return ebb
|
||||
return ebbb
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,11 +71,33 @@ object MessageUtil {
|
|||
}
|
||||
}
|
||||
|
||||
///Get a cloned embedded message, missing only the fields
|
||||
fun getAClonedEmbedd(e: Embed): EmbedBuilder {
|
||||
///Get a cloned embedded message
|
||||
fun getAClonedEmbed(e: Embed): EmbedBuilder {
|
||||
val ebb = EmbedBuilder()
|
||||
ebb.color = e.color
|
||||
ebb.title = e.title
|
||||
e.fields.forEach {
|
||||
val fb = EmbedBuilder.Field()
|
||||
fb.name = it.name
|
||||
fb.value = it.value
|
||||
fb.inline = it.inline
|
||||
ebb.fields.add(fb)
|
||||
}
|
||||
ebb.description = e.description
|
||||
return ebb
|
||||
}
|
||||
|
||||
fun getAClonedEmbed(e: EmbedBuilder): EmbedBuilder {
|
||||
val ebb = EmbedBuilder()
|
||||
ebb.color = e.color
|
||||
ebb.title = e.title
|
||||
e.fields.forEach {
|
||||
val fb = EmbedBuilder.Field()
|
||||
fb.name = it.name
|
||||
fb.value = it.value
|
||||
fb.inline = it.inline
|
||||
ebb.fields.add(fb)
|
||||
}
|
||||
ebb.description = e.description
|
||||
return ebb
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue