Skip to content

Instantly share code, notes, and snippets.

@devblackops
Last active July 16, 2019 05:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devblackops/2b02fbb946a421de6efb5b9c8ce7d79b to your computer and use it in GitHub Desktop.
Save devblackops/2b02fbb946a421de6efb5b9c8ce7d79b to your computer and use it in GitHub Desktop.
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