-
Notifications
You must be signed in to change notification settings - Fork 75
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
Automatically leave voice channel after some time spent idle #42
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've changed the bot so that it will leave once the queue is empty after approximately 10 minutes without explanation
This is probably not what all Ukulele users want. This feature should default to be disabled.
@@ -9,5 +9,6 @@ class BotProps( | |||
var prefix: String = "::", | |||
var database: String = "./database", | |||
var game: String = "", | |||
var trackDurationLimit: Int = 0 | |||
var trackDurationLimit: Int = 0, | |||
var idleTimeMinutes: Int = 10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be disabled by default
var idleTimeMinutes: Int = 10 | |
var idleTimeMinutes: Int = 0 |
Okay, so in the process of reworking the PR with code review feedback I discovered a race condition of sorts. Basically, oftentimes the I tried a couple things to resolve the issue. I first tried implementing |
class Player( | ||
private val beans: Beans, | ||
guildProperties: GuildProperties, | ||
private val leaveOnIdleService: LeaveOnIdleService, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're actually supposed to put this value in the Beans class and not change PlayerRegistry
at all
* Create a new timer which will start counting from the current moment and cancel any existing timers | ||
* associated with this guild. | ||
*/ | ||
fun maybeCreateTimer(guild: Guild) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A more appropriate name is onQueueEmpty
. The player doesn't control this service
/** | ||
* If a timer exists for this guild, cancel it. | ||
*/ | ||
fun maybeDestroyTimer(guild: Guild) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destroyTimer
sounds better. We don't need to communicate that there might not be a timer to destroy
// don't do anything if idleTimeMinutes is not set | ||
if (botProps.idleTimeMinutes <= 0) return | ||
|
||
timers[guild.idLong]?.let { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do timers.remove(guild.idLong)?.let { ... }
and delete the other remove call
* a player in a guild has spent idling. | ||
*/ | ||
class IdleTask(val guild: Guild, private val idleTimeMinutes: Int) : Runnable { | ||
private var numberOfMinutesIdleElapsed = -1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit odd to me that you're using a counter and not a unix timestamp, but I suppose this works too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, could you not just schedule the voice leave after idleTimeMinutes
minutes?
* Runnable that gets passed to the Spring TaskScheduler. Used to keep track of how many minutes | ||
* a player in a guild has spent idling. | ||
*/ | ||
class IdleTask(val guild: Guild, private val idleTimeMinutes: Int) : Runnable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you make this an inner class
you don't need to pass idleTimeMinutes
Hi, anything else I can do to move this along? I believed I've addressed all the comments from the last round of review. |
Hi SriRamanujam, Freya is currently focusing her time on her bachelor project until the 4th of January, I would probably expect replies to be sparse until then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the wait! There's one small thing I want you to change still
src/main/kotlin/dev/arbjerg/ukulele/features/LeaveOnIdleService.kt
Outdated
Show resolved
Hide resolved
Unfortunately, trying to model the task as a duration-based timeout saw race conditions where the callback to determine whether to start a timer was called before the callback to add a new track to the player had run. This caused an issue where the code believed that no track was playing when in fact a track would be queued mere milliseconds later. When the video in question was under a minute long, this led to a state where the bot would leave the channel a minute early. I've re-implemented the functionality such that it is invoked as part of the onTrackStart and onTrackEnd callbacks of Player. This guarantees that the idle timer kickoff logic runs _after_ all other Player state updates have completed, which neatly avoids race/ordering bugs.
* put leaveOnIdleService in Player.Beans * better names for leaveOnIdleService's callbacks * Directly call timers.remove() * Schedule VC leave task directly, rather than periodically calling timer * Clean up redundant comments
a54c36c
to
b623ad2
Compare
This PR enables the bot to leave a voice channel after some time spent idle. Upon joining a channel, a scheduled task will fire every minute that checks to see if the player is idle. If it is, the task will increment an internal timer. After some configurable amount of time (
idleTimeMinutes
inukulele.yml
, defaults to 10 minutes) the task will have the bot automatically leave the voice channel.First time working with Kotlin and Spring, so please do point out any stylistic foibles. If there's a linter I should run, I can do that no problem.
Fixes #26