Handle Discord token rate limits sanely

This commit is contained in:
Meta Vens 2026-05-08 20:39:58 +01:00
commit f60a1043a4
2 changed files with 112 additions and 4 deletions

View file

@ -185,6 +185,82 @@ function Get-Json {
return $response | ConvertFrom-Json
}
function Invoke-JsonRequestDetailed {
param(
[Parameter(Mandatory = $true)]
[string] $Url,
[string[]] $Headers = @()
)
$headerPath = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
try {
$args = @(
"-sS",
"--connect-timeout", "5",
"--max-time", "20",
"-D", $headerPath,
$Url
)
foreach ($header in $Headers) {
$args = @("-H", $header) + $args
}
$responseBody = & curl.exe @args
$exitCode = $LASTEXITCODE
$headerLines = if (Test-Path -LiteralPath $headerPath) {
Get-Content -LiteralPath $headerPath
} else {
@()
}
$statusCode = $null
$statusLine = @($headerLines | Where-Object { $_ -match "^HTTP/" } | Select-Object -Last 1)
if ($statusLine.Count -gt 0 -and $statusLine[0] -match "^HTTP/\S+\s+(\d{3})") {
$statusCode = [int]$Matches[1]
}
$parsedHeaders = @{}
foreach ($line in $headerLines) {
if ([string]::IsNullOrWhiteSpace($line) -or $line -match "^HTTP/") {
continue
}
$separatorIndex = $line.IndexOf(":")
if ($separatorIndex -lt 1) {
continue
}
$name = $line.Substring(0, $separatorIndex).Trim()
$value = $line.Substring($separatorIndex + 1).Trim()
$parsedHeaders[$name] = $value
}
if ($exitCode -ne 0 -and $null -eq $statusCode) {
throw "Request failed for $Url"
}
$json = $null
if (-not [string]::IsNullOrWhiteSpace($responseBody)) {
try {
$json = $responseBody | ConvertFrom-Json
} catch {
}
}
return @{
statusCode = $statusCode
headers = $parsedHeaders
body = $responseBody
json = $json
exitCode = $exitCode
}
} finally {
Remove-Item -LiteralPath $headerPath -Force -ErrorAction SilentlyContinue
}
}
function Invoke-CommandWithTimeout {
param(
[Parameter(Mandatory = $true)]
@ -963,10 +1039,41 @@ try {
if ($config.ContainsKey("DISCORD_BOT_TOKEN") -and -not [string]::IsNullOrWhiteSpace($config["DISCORD_BOT_TOKEN"])) {
Set-WatchdogStep -CurrentStep "discord_checks" -Detail "Validating Discord bot credentials."
try {
$botIdentity = Get-Json -Url "https://discord.com/api/v10/users/@me" -Headers @("Authorization: Bot $($config["DISCORD_BOT_TOKEN"])")
Add-Check -Name "discord.bot_token" -Status "passed" -Detail "Discord bot token is valid for $([string]$botIdentity.username)." -Data @{
id = [string]$botIdentity.id
username = [string]$botIdentity.username
$discordIdentityResponse = Invoke-JsonRequestDetailed -Url "https://discord.com/api/v10/users/@me" -Headers @("Authorization: Bot $($config["DISCORD_BOT_TOKEN"])")
$statusCode = $discordIdentityResponse.statusCode
if ($statusCode -eq 200 -and $null -ne $discordIdentityResponse.json) {
$botIdentity = $discordIdentityResponse.json
Add-Check -Name "discord.bot_token" -Status "passed" -Detail "Discord bot token is valid for $([string]$botIdentity.username)." -Data @{
id = [string]$botIdentity.id
username = [string]$botIdentity.username
}
} elseif ($statusCode -eq 429) {
$retryAfterSeconds = $null
if ($discordIdentityResponse.headers.ContainsKey("Retry-After")) {
[double]::TryParse([string]$discordIdentityResponse.headers["Retry-After"], [ref]$retryAfterSeconds) | Out-Null
}
$detail = if ($null -ne $retryAfterSeconds) {
"Discord bot token check was rate-limited by Discord (429). Retry after about $retryAfterSeconds second(s); the token is not necessarily bad."
} else {
"Discord bot token check was rate-limited by Discord (429). The token is not necessarily bad."
}
Add-Check -Name "discord.bot_token" -Status "warning" -Detail $detail -Data @{
statusCode = $statusCode
retryAfterSeconds = $retryAfterSeconds
}
} else {
$message = if ($null -ne $discordIdentityResponse.json -and $discordIdentityResponse.json.PSObject.Properties.Name -contains "message") {
[string]$discordIdentityResponse.json.message
} else {
"Request failed for https://discord.com/api/v10/users/@me"
}
Add-Check -Name "discord.bot_token" -Status "failed" -Detail "Discord bot token check failed ($statusCode): $message" -Data @{
statusCode = $statusCode
}
}
} catch {
Add-Check -Name "discord.bot_token" -Status "failed" -Detail "Discord bot token check failed: $($_.Exception.Message)"

View file

@ -64,3 +64,4 @@
{"ts":"2026-05-08T15:50:57Z","type":"architecture","status":"ok","note":"Moderation novelty now needs two bars, not one: room novelty and self novelty. The memory organ merges repeated seams into existing clusters, raises saturation and refractory pressure, tracks source-coverage pressure across repos/archive terrain, and cools familiar thoughts instead of rewarding repetition with ripeness."}
{"ts":"2026-05-08T16:00:51Z","type":"architecture","status":"ok","note":"Manual moderation-state distillation showed the memory surface was overproducing near-duplicate repo-weather thoughts by storing each social flavor of the same seam as a separate semantic card, sweep, and synthesis. Periodic cleanup should merge those variants by conceptual family, rebalance recent source traces, and clear stale resonance/incubation caches so novelty pressure can regrow from a cleaner substrate."}
{"ts":"2026-05-08T16:06:43Z","type":"architecture","status":"ok","note":"Quiet-room moderation no longer treats retrieval as compulsory ritual. If incubation already holds a live, grounded, low-saturation thought, Void may deepen it directly; archive dives and repo sweeps are now explicit support for hungry, stale, or oversaturated queues rather than mandatory throat-clearing before every private thought."}
{"ts":"2026-05-08T19:39:40Z","type":"implementation","status":"ok","note":"Discord bot token health checks can hit Discord API rate limits even when the token is fine. The watchdog now distinguishes HTTP 429 from actual credential failures, downgrading rate limits to a warning with retry-after data instead of reporting a dead token."}