PoshBot middlware hook to notify chatty people in a Slack channel to use threaded conversations if they post too many messages in a short time interval
<# | |
.SYNOPSIS | |
Suggest Slack threads for talkative users. | |
.DESCRIPTION | |
This middleware tracks how many messages (x) users send per (y) amount of time. | |
If a user goes over the threshold, we'll send a message suggesting that Slack threads should be used. | |
.NOTES | |
Based on https://stackoverflow.com/questions/667508/whats-a-good-rate-limiting-algorithm | |
#> | |
param( | |
$Context, | |
$Bot | |
) | |
$Bot.LogDebug('Beginning message ratelimit middleware') | |
# We'll allow (5) messages per user in a 60 second window before suggesting threads | |
$maxMsgs = 6 | |
$timePeriod = 60 | |
$userId = $Context.Message.From | |
$timePeriodMS = $timePeriod * 1000 | |
# Only measure messages NOT already in a thread | |
# This middlware hook stage also receives extra messages whenever a user replies in a thread | |
# We need to ensure we DON'T count these against the rate limiting | |
$unThreadedMsg = ( | |
([string]::IsNullOrWhiteSpace($Context.Message.RawMessage.thread_ts) -and | |
($Context.Message.RawMessage.type -eq 'message' -and $Context.Message.RawMessage.subtype -ne 'message_replied')) | |
) | |
if ($unThreadedMsg) { | |
# Load the tracker | |
$trackerPath = Join-Path $Bot.Configuration.ConfigurationDirectory 'msg_ratelimiting_tracking.clixml' | |
if (Test-Path $trackerPath) { | |
$tracker = Import-Clixml $trackerPath | |
} else { | |
$tracker = @{ | |
$userId = @{ | |
Allowance = $maxMsgs | |
LastMsgTime = [datetime]::UtcNow | |
} | |
} | |
} | |
$now = [datetime]::UtcNow | |
$timePassed = ($now - $tracker[$userId].LastMsgTime).TotalSeconds | |
$tracker[$userId].LastMsgTime = $now | |
$tracker[$userId].Allowance += $timePassed * ($maxMsgs / $timePeriodMS) | |
if ($tracker[$userId].Allowance -gt $maxMsgs) { | |
$tracker[$userId].Allowance = $maxMsgs | |
} | |
If ($tracker[$userId].Allowance -lt 1.0) { | |
$Bot.LogDebug("User [$userId] has breached ratelimit of [$maxMsgs] messages in [$timePeriod)] seconds. Sending thread reminder response") | |
$response = [Response]::new() | |
$response.To = $Context.Message.To | |
$response.MessageFrom = $Context.Message.From | |
$response.OriginalMessage = $Context.Message | |
$mentionUser = "<@$($Context.Message.From)>" | |
$text = "Hey $mentionUser, we noticed you have a lot to say. Perhaps creating a Slack thread would be useful." | |
$response.Data = New-PoshBotTextResponse -Text $text -AsCode | |
$Bot.SendMessage($response) | |
$Bot.LogDebug('Sending thread reminding response') | |
# Reset so we don't send again until they breach the limit again | |
$tracker[$userId].Allowance = $maxMsgs | |
} else { | |
$tracker[$userId].Allowance -= 1.0 | |
} | |
$tracker | Export-Clixml -Path $trackerPath | |
} else { | |
$Bot.LogDebug("Ignoring message. It's already in a threaded conversation.") | |
} | |
# Return context back for any subsequent middleware | |
$Bot.LogDebug('Ending message ratelimit middleware') | |
$Context |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment