Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

/poll command: 發起投票,且一定時間後結束投票並展示投票結果 #100

Merged
merged 4 commits into from
Jun 9, 2023

Conversation

Johnny850807
Copy link
Contributor

@Johnny850807 Johnny850807 commented May 21, 2023

Why need this change? / Root cause:

Changes made:

  • when use poll command, bot will respond the embedded message with polling options
  • work in progress (toggle: off)

Test Scope / Change impact:

  • /poll

Summary by OpenAI

Release Notes:

  • New Feature: Added /poll command to initiate a polling session and permit Discord members to cast their votes for various options within a specified amount of time.
  • New Feature: Added functionality to observe and remove members from a list periodically in gaas.
  • New Feature: Added a new subcommand for muting audiences and fixed a logical error in the MuteAudiences class in audio-experience.
  • Bug fix: Modified existing functions in discord-impl-jda to retrieve options from a Discord slash command interaction event with validation.
  • Chore: Added new dependencies to the project.

"New features, bug fixes galore,
Our codebase is better than before.
With polls, gaas, and mute commands too,
Our Discord bot is fresh and new."

frankvicky
frankvicky previously approved these changes May 22, 2023
Copy link
Collaborator

@frankvicky frankvicky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Johnny850807 Johnny850807 changed the title /poll command: when use poll command, bot will respond the embedded message with polling options /poll command: 發起投票,且一定時間後結束投票並展示投票結果 May 28, 2023
@github-actions
Copy link

github-actions bot commented May 28, 2023

🤖 OpenAI

Summary of Changes

The changes involve modifications to the functionality of the codebase, including adding new features, modifying existing functions, and adding dependencies. The changes could impact the behavior of the code and introduce bugs or security vulnerabilities. Therefore, a thorough review is necessary to ensure the logic, security, performance, and maintainability of the code.

File Summary
audio-experience/src/main/kotlin/tw/waterballsa/utopia/audiox/MuteAudiences.kt Adds a new subcommand for muting audiences and fixes a logical error in the isNotMuteCommand() function.
discord-impl-jda/src/main/kotlin/tw/waterballsa/utopia/jda/extensions/GenericCommandInteractionEventExtension.kt Adds a new function getOptionAsLongInRange and modifies the existing function getOptionAsLongWithValidation. These functions are used to retrieve options from a Discord slash command interaction event with validation.
discord-impl-jda/src/main/kotlin/tw/waterballsa/utopia/jda/jda.kt Adds a private modifier to a logger variable.
gaas/src/main/kotlin/tw/waterballsa/utopia/gaas/ObserveMember.kt Adds functionality to observe and remove members from a list periodically. Includes a timer task to remove expired members from the list.
main/pom.xml Adds a new dependency to the project and includes changes to implement a /poll command that responds with an embedded message containing polling options.
poll/pom.xml Adds dependencies to the project.
poll/src/main/kotlin/tw.waterballsa.utopia.poll/PollCommandListener.kt Adds a new feature to initiate a polling session and permit Discord members to cast their votes for various options within a specified amount of time.
pom.xml Adds a new module for polling and includes dependencies for it.
wsa-bot-commands.md Adds new commands for gaas, russian-roulette, mute, and audience. Modifies /poll command to respond with embedded message with polling options. Minor changes to existing commands.

Chat with 🤖 OpenAI Bot (@openai)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @openai in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Ignoring further reviews

  • Type @openai: ignore anywhere in the PR description to ignore further reviews from the bot.


In the recent run, only the files that changed from the base of the PR and between bd0a4b2a571185803a7bb777603d978d4649d511 and 35641906134af424bc0d2112b87f01420c177390 commits were reviewed.

Files not reviewed due to simple changes (1)

Skipped review in the recent run

  • poll/pom.xml

Comment on lines 21 to 22
import tw.waterballsa.utopia.jda.JdaInstance.compositeListener
import java.lang.reflect.Method
Copy link

@github-actions github-actions bot May 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The import statements are not sorted in alphabetical order. Please sort them.

Suggested change
import tw.waterballsa.utopia.jda.JdaInstance.compositeListener
import java.lang.reflect.Method
import java.lang.reflect.Method
import tw.waterballsa.utopia.jda.JdaInstance.compositeListener

Comment on lines +82 to +102
fun removeExpiredMembersPeriodically(jda: JDA, properties: WsaDiscordProperties) = listener {
val guild = jda.getGuildById(properties.guildId)!!
val role = jda.getRoleById(properties.wsaGaaSMemberRoleId)!!

timer.onStart(
removeExpiredMemberRolePeriodically(guild, role),
now().atStartOfDay().toDate(),
24.hours.inWholeMilliseconds
)
}

private fun removeExpiredMemberRolePeriodically(
guild: Guild,
role: Role
) = timerTask {
observedMemberRepository.findAll()
.filter { it.isCreatedTimeOver30Days() }
.takeIf { it.isNotEmpty() }
?.onEach { removeRoleFromRecord(guild, it, role) }
?.map { it.id }
?.let { observedMemberRepository.removeObservedMemberByIds(it) }
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The new code adds a new function removeExpiredMembersPeriodically that removes expired members from the observed member repository periodically. The implementation looks good, but there is an opportunity to improve performance by using a more efficient data structure for storing the observed members. Consider using a hash set or a map instead of a list to store the observed members to improve lookup time.

main/pom.xml Outdated Show resolved Hide resolved
Comment on lines 24 to 35
## poll
| Commands | Arguments | Description |
|:--------:|:-------------------------------:|:-----------:|
| poll | time time-unit question options | <TODO> |

Copy link

@github-actions github-actions bot May 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The new /poll command has been added to the document. The description for the command is missing and marked as <TODO>. Please update the description to provide a clear explanation of what the command does and how it works.

Comment on lines +31 to +33
private const val OPTION_QUESTION = "question"

private const val OPTION_OPTIONS = "options"
Copy link

@github-actions github-actions bot May 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The pollOptionStrings variable is not being used. Is this intentional? If so, please remove the variable declaration and assignment.

Suggested change
private const val OPTION_QUESTION = "question"
private const val OPTION_OPTIONS = "options"
// Remove pollOptionStrings variable declaration and assignment

Comment on lines +23 to +25
fun observeMember(properties: WsaDiscordProperties) = listener {
on<SlashCommandInteractionEvent> {
val targetUser = getOptionsByType(OptionType.USER).first().asMember!!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The getOptionsByType function call may throw an exception if no options of type OptionType.USER are found. Consider adding error handling to handle this case.

Suggested change
fun observeMember(properties: WsaDiscordProperties) = listener {
on<SlashCommandInteractionEvent> {
val targetUser = getOptionsByType(OptionType.USER).first().asMember!!
val targetUser = getOptionsByType(OptionType.USER).firstOrNull()?.asMember
if (targetUser == null) {
replyEphemerally("No user option found.")
return@on
}

Comment on lines +27 to +28
val commandUser = member!!
val gaaSMemberRoleId = properties.wsaGaaSMemberRoleId

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

Consider extracting the alphaRoleId and wsaGaaSMemberRoleId values into a separate function or class to avoid code duplication.

Suggested change
val commandUser = member!!
val gaaSMemberRoleId = properties.wsaGaaSMemberRoleId
private fun getRoleIds(properties: WsaDiscordProperties): Pair<Long, Long> {
return properties.wsaAlphaRoleId to properties.wsaGaaSMemberRoleId
}
// Usage
val (alphaRoleId, gaaSMemberRoleId) = getRoleIds(properties)

Comment on lines +30 to +41
when {
interaction.fullCommandName != "gaas observe" -> return@on
!commandUser.isAlphaMember(alphaRoleId) -> {
replyEphemerally("權限不足")
return@on
}

!targetUser.isGaaSMember(gaaSMemberRoleId) -> {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return@on
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

Consider extracting the permission checks into a separate function or class to improve readability and maintainability.

Suggested change
when {
interaction.fullCommandName != "gaas observe" -> return@on
!commandUser.isAlphaMember(alphaRoleId) -> {
replyEphemerally("權限不足")
return@on
}
!targetUser.isGaaSMember(gaaSMemberRoleId) -> {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return@on
}
}
private fun checkPermissions(
interaction: SlashCommandInteractionEvent,
commandUser: Member,
alphaRoleId: Long,
targetUser: Member?,
gaaSMemberRoleId: Long
): Boolean {
if (interaction.fullCommandName != "gaas observe" && interaction.fullCommandName != "gaas unobserve") {
return false
}
if (!commandUser.isAlphaMember(alphaRoleId)) {
replyEphemerally("權限不足")
return false
}
if (targetUser != null && !targetUser.isGaaSMember(gaaSMemberRoleId)) {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return false
}
return true
}
// Usage
val (alphaRoleId, gaaSMemberRoleId) = getRoleIds(properties)
val targetUser = getOptionsByType(OptionType.USER).firstOrNull()?.asMember
if (!checkPermissions(interaction, commandUser, alphaRoleId, targetUser, gaaSMemberRoleId)) {
return@on
}

Comment on lines +43 to +46
if (observedMemberRepository.exists(targetUser.id)) {
replyEphemerally("${targetUser.asMention} 已經在觀察名單")
return@on
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

Consider extracting the check for an existing observed member into a separate function or class to improve readability and maintainability.

Suggested change
if (observedMemberRepository.exists(targetUser.id)) {
replyEphemerally("${targetUser.asMention} 已經在觀察名單")
return@on
}
private fun checkExistingObservedMember(targetUserId: String): Boolean {
if (observedMemberRepository.exists(targetUserId)) {
replyEphemerally("${targetUser.asMention} 已經在觀察名單")
return true
}
return false
}
// Usage
if (checkExistingObservedMember(targetUser.id)) {
return@on
}

Comment on lines +54 to +78
fun removeMember(properties: WsaDiscordProperties) = listener {
on<SlashCommandInteractionEvent> {
val targetUser = getOptionsByType(OptionType.USER).first().asMember!!
val alphaRoleId = properties.wsaAlphaRoleId
val commandUser = member!!
val gaaSMemberRoleId = properties.wsaGaaSMemberRoleId

when {
interaction.fullCommandName != "gaas unobserve" -> return@on
!commandUser.isAlphaMember(alphaRoleId) -> {
replyEphemerally("權限不足")
return@on
}

!targetUser.isGaaSMember(gaaSMemberRoleId) -> {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return@on
}
}

if (observedMemberRepository.exists(targetUser.id)) {
observedMemberRepository.removeObservedMember(targetUser.id)
}
replyEphemerally("${targetUser.asMention} 已經從觀察名單移除")
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

Consider extracting the removeMember function into a separate class or function to avoid code duplication with the observeMember function.

Suggested change
fun removeMember(properties: WsaDiscordProperties) = listener {
on<SlashCommandInteractionEvent> {
val targetUser = getOptionsByType(OptionType.USER).first().asMember!!
val alphaRoleId = properties.wsaAlphaRoleId
val commandUser = member!!
val gaaSMemberRoleId = properties.wsaGaaSMemberRoleId
when {
interaction.fullCommandName != "gaas unobserve" -> return@on
!commandUser.isAlphaMember(alphaRoleId) -> {
replyEphemerally("權限不足")
return@on
}
!targetUser.isGaaSMember(gaaSMemberRoleId) -> {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return@on
}
}
if (observedMemberRepository.exists(targetUser.id)) {
observedMemberRepository.removeObservedMember(targetUser.id)
}
replyEphemerally("${targetUser.asMention} 已經從觀察名單移除")
}
private fun removeObservedMember(
properties: WsaDiscordProperties,
interaction: SlashCommandInteractionEvent,
observedMemberRepository: ObservedMemberRepository
) = listener {
val targetUser = getOptionsByType(OptionType.USER).firstOrNull()?.asMember
val (alphaRoleId, gaaSMemberRoleId) = getRoleIds(properties)
val commandUser = member!!
if (!checkPermissions(interaction, commandUser, alphaRoleId, targetUser, gaaSMemberRoleId)) {
return@listener
}
if (!checkExistingObservedMember(targetUser!!.id)) {
observedMemberRepository.removeObservedMember(targetUser.id)
replyEphemerally("${targetUser.asMention} 已經從觀察名單移除")
}
}
// Usage
removeObservedMember(properties, interaction, observedMemberRepository)

Comment on lines +85 to +89
timer.onStart(
removeExpiredMemberRolePeriodically(guild, role),
now().atStartOfDay().toDate(),
24.hours.inWholeMilliseconds
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

Consider using the Timer.scheduleAtFixedRate function instead of onStart to schedule the task to run periodically.

Suggested change
timer.onStart(
removeExpiredMemberRolePeriodically(guild, role),
now().atStartOfDay().toDate(),
24.hours.inWholeMilliseconds
)
timer.scheduleAtFixedRate(
removeExpiredMemberRolePeriodically(guild, role),
now().atStartOfDay().toDate(),
24.hours.inWholeMilliseconds
)

Copy link
Collaborator

@Wally5077 Wally5077 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review done.

Copy link
Collaborator

@Wally5077 Wally5077 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Johnny850807 Johnny850807 merged commit a2f251c into main Jun 9, 2023
@Johnny850807 Johnny850807 deleted the feat/98 branch June 9, 2023 17:37
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jun 9, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

1.0% 1.0% Coverage
20.5% 20.5% Duplication

Comment on lines +18 to +22
fun GenericCommandInteractionEvent.getOptionAsLongInRange(name: String, range: LongRange): Long? {
return getOptionAsLongWithValidation(name, "a long that within ${range.first} ~ ${range.last}") {
range.contains(it)
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The getOptionAsLongInRange function seems to have a typo in the name of the function. It should be getOptionAsLongWithValidation. Also, the validation message could be improved by using a more readable format string. Consider changing line 19 to:

return getOptionAsLongWithValidation(name, "a long within the range ${range.first} to ${range.last}") {
    range.contains(it)
}

Comment on lines 15 to 26
}
}

fun GenericCommandInteractionEvent.getOptionAsLongInRange(name: String, range: LongRange): Long? {
return getOptionAsLongWithValidation(name, "a long that within ${range.first} ~ ${range.last}") {
range.contains(it)
}
}

fun GenericCommandInteractionEvent.getOptionAsIntInRange(name: String, range: IntRange): Int? {
return getOptionAsIntWithValidation(name, "a integer that within ${range.first} ~ ${range.last}") {
range.contains(it)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [24-28]

Similar to the previous hunk, the getOptionAsIntInRange function has a typo in its name and should be changed to getOptionAsIntWithValidation. Additionally, the validation message could be improved by using a more readable format string. Consider changing line 25 to:

return getOptionAsIntWithValidation(name, "an integer within the range ${range.first} to ${range.last}") {
    range.contains(it)
}

Comment on lines 39 to 50
return getOptionWithValidation(name, optionTypeName, validation) { it?.asString }
}

fun GenericCommandInteractionEvent.getOptionAsLongWithValidation(name: String,
optionTypeName: String,
validation: (Long) -> Boolean): Long? {
return getOptionWithValidation(name, optionTypeName, validation) { it?.asLong }
}

fun GenericCommandInteractionEvent.getOptionAsIntWithValidation(name: String,
optionTypeName: String,
validation: (Int) -> Boolean): Int? {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [48-52]

Similar to the previous hunk, the getOptionAsIntWithValidation function seems to be missing a parameter for the option type name. Consider adding it as the second parameter and updating the call sites accordingly.

Comment on lines +9 to +14
| Commands | Arguments | Description |
|:----------------------:| -------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| gaas stats-avg-and-max | event-date-year(INTEGER): Year<br>event-date-month(INTEGER): Month<br>event-date-day(INTEGER): Day | Get Avg And Max Participants Number at Specific Date |
| gaas observe | gaas-member(USER): GaaS Member | Add a specific member to the watchlist |
| gaas unobserved | gaas-member(USER): GaaS Member | Remove a specific member from the watchlist |

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The gaas subcommand seems to be missing input validation for the gaas-member argument. It is recommended to validate that the user provided as an argument is actually a member of the GaaS team before adding or removing them from the watchlist. This can prevent unauthorized access to sensitive information.

Comment on lines +15 to 19
## russian-roulette
| Commands | Arguments | Description |
|:----------------:| --------- | ------------ |
| russian-roulette | | GaaS Command |

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The russian-roulette subcommand seems to be incomplete. Please provide more details on what this command does and how it works.

Comment on lines 21 to 24
| Commands | Arguments | Description |
|:--------------:| ---------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| audio breakout | room-size(INTEGER): Number of members per room.<br>countdown(INTEGER): Countdown time in seconds.<br>room-name(STRING): The name prefix of per room. | Create breakout rooms. |

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The audio breakout subcommand seems to be missing input validation for the room-size, countdown, and room-name arguments. It is recommended to validate that these arguments are within reasonable limits and do not cause any performance issues or security vulnerabilities.

Comment on lines +23 to +50
fun observeMember(properties: WsaDiscordProperties) = listener {
on<SlashCommandInteractionEvent> {
val targetUser = getOptionsByType(OptionType.USER).first().asMember!!
val alphaRoleId = properties.wsaAlphaRoleId
val commandUser = member!!
val gaaSMemberRoleId = properties.wsaGaaSMemberRoleId

when {
interaction.fullCommandName != "gaas observe" -> return@on
!commandUser.isAlphaMember(alphaRoleId) -> {
replyEphemerally("權限不足")
return@on
}

!targetUser.isGaaSMember(gaaSMemberRoleId) -> {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return@on
}
}

if (observedMemberRepository.exists(targetUser.id)) {
replyEphemerally("${targetUser.asMention} 已經在觀察名單")
return@on
}

observedMemberRepository.addObservedMember(targetUser.toObservedMemberRecord())
replyEphemerally("${targetUser.asMention} 已經成功加入觀察名單")
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

The observeMember function seems to be handling a slash command event and adding a user to an observed member list. There are several issues with this code:

  • The function is doing too many things at once, including input validation, permission checking, and database operations. It would be better to split these responsibilities into separate functions.
  • The function is using magic strings for command names instead of constants or enums.
  • The function is using return@on statements to exit early from the function. This can make the code harder to read and understand.
  • The function is not handling errors or exceptions that may occur during its execution.
Suggested change
fun observeMember(properties: WsaDiscordProperties) = listener {
on<SlashCommandInteractionEvent> {
val targetUser = getOptionsByType(OptionType.USER).first().asMember!!
val alphaRoleId = properties.wsaAlphaRoleId
val commandUser = member!!
val gaaSMemberRoleId = properties.wsaGaaSMemberRoleId
when {
interaction.fullCommandName != "gaas observe" -> return@on
!commandUser.isAlphaMember(alphaRoleId) -> {
replyEphemerally("權限不足")
return@on
}
!targetUser.isGaaSMember(gaaSMemberRoleId) -> {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return@on
}
}
if (observedMemberRepository.exists(targetUser.id)) {
replyEphemerally("${targetUser.asMention} 已經在觀察名單")
return@on
}
observedMemberRepository.addObservedMember(targetUser.toObservedMemberRecord())
replyEphemerally("${targetUser.asMention} 已經成功加入觀察名單")
}
fun observeMember(properties: WsaDiscordProperties) = listener {
on<SlashCommandInteractionEvent> {
val targetUser = getOptionsByType(OptionType.USER).first().asMember!!
val alphaRoleId = properties.wsaAlphaRoleId
val commandUser = member!!
val gaaSMemberRoleId = properties.wsaGaaSMemberRoleId
if (!isAuthorizedToObserve(commandUser, alphaRoleId)) {
replyEphemerally("權限不足")
return@on
}
if (!isGaaSMember(targetUser, gaaSMemberRoleId)) {
replyEphemerally("${targetUser.asMention} 並非 GaaS 成員")
return@on
}
try {
addObservedMember(targetUser.toObservedMemberRecord())
replyEphemerally("${targetUser.asMention} 已經成功加入觀察名單")
} catch (e: Exception) {
log.error(e) { "Failed to add observed member ${targetUser.id}" }
replyEphemerally("無法加入觀察名單")
}
}
}
private fun isAuthorizedToObserve(user: Member, alphaRoleId: Long): Boolean {
return user.isAlphaMember(alphaRoleId)
}
private fun isGaaSMember(user: Member, gaaSMemberRoleId: Long): Boolean {
return user.isGaaSMember(gaaSMemberRoleId)
}
private fun addObservedMember(record: ObservedMemberRecord) {
if (observedMemberRepository.exists(record.id)) {
throw IllegalArgumentException("User ${record.id} already exists in observed member list")
}
observedMemberRepository.addObservedMember(record)
}

---new_hunk---

110: private fun removeExpiredMemberRolePeriodically(
111:         guild: Guild,
112:         role: Role
113: ) = timerTask {
114:     observedMemberRepository.findAll()
115:             .filter { it.isCreatedTimeOver30Days() }
116:             .takeIf { it.isNotEmpty() }
117:             ?.onEach { removeRoleFromRecord(guild, it, role) }
118:             ?.map { it.id }
119:             ?.let { observedMemberRepository.removeObservedMemberByIds(it) }
120: }
121: 
122: private fun removeRoleFromRecord(guild: Guild, record: ObservedMemberRecord, role: Role) {
123:     guild.removeRoleFromMember(UserSnowflake.fromId(record.id), role).queue {
124:         log.info { "[Observe] {\"Observe\" : \"Remove the expired Member [${record.name}]. \"}" }
125:     }
126: }

---old_hunk---


---end_change_section---

Comment on lines 76 to +83
<groupId>tw.waterballsa.utopia</groupId>
<artifactId>audience-counter</artifactId>
</dependency>

<!-- <dependency>-->
<!-- <groupId>tw.waterballsa.utopia</groupId>-->
<!-- <artifactId>poll</artifactId>-->
<!-- </dependency>-->
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 OpenAI

A new dependency for poll has been commented out. It's unclear why it was commented out, but if it's no longer needed, it should be removed entirely. If it is still needed, it should be uncommented and added to the dependencies section.

Suggested change
<groupId>tw.waterballsa.utopia</groupId>
<artifactId>audience-counter</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>tw.waterballsa.utopia</groupId>-->
<!-- <artifactId>poll</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>tw.waterballsa.utopia</groupId>
<artifactId>poll</artifactId>
</dependency>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants