fix: skip token-less webhooks in pick(); self-heal deletes the dead pick, not the managed webhook
dpywebhooks-1 (HIGH): pick()/send_any could select token-less channel-follower (type 2) or application-owned (type 3) webhooks returned by channel.webhooks(). Webhook.send raises a raw ValueError on those before any HTTP call, and send_any only caught discord.HTTPException, so the ValueError bypassed fallback and self-heal entirely. strategy='first' picks the lowest id, so any channel following an announcement channel could be permanently broken. Fix: pick() now filters candidates to w.token is not None. dpywebhooks-2 (HIGH): send_any's self-heal always called clear(), which targets the managed webhook (cache/store), not the dead webhook that was actually picked. When the dead pick and the managed webhook differed, this deleted a healthy managed webhook and churned delete+create toward the 10-cap on every send. Fix: self-heal now deletes the dead picked webhook directly (bot-auth webhook.delete() authorizes on it without its own token); clear() is only used when the pick IS the managed webhook. dpywebhooks-8 (nit): count() and _create() now read live webhooks through list() instead of calling channel.webhooks() directly, so the token filter and any future list() change reach all three call sites from one source. Version 0.1.0 -> 0.1.1. README + module docstrings updated to document the token filter and the corrected self-heal delete target. Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
@@ -8,7 +8,7 @@ each time (wasteful, rate-limited, and it leaks toward the cap).
|
||||
## Install
|
||||
|
||||
```
|
||||
dpy_webhooks @ git+ssh://git@git.rethinkstudios.io/rethink-public/dpy_webhooks.git@v0.1.0
|
||||
dpy_webhooks @ git+ssh://git@git.rethinkstudios.io/rethink-public/dpy_webhooks.git@v0.1.1
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -38,9 +38,13 @@ await hooks.send_any(channel, strategy="round_robin", content="hi") # send via
|
||||
|
||||
`pick` strategies are `"first"` (oldest by id), `"random"`, and `"round_robin"` (per-channel
|
||||
in-process index that wraps on the live count and rebuilds if the count changed); an unknown
|
||||
strategy raises `ValueError`. `send_any` sends through a picked existing webhook, **falling
|
||||
back to `get_or_create`** when the channel has none, and reuses the same dead-webhook
|
||||
self-heal. None of these three create or touch the store — they read live from the channel.
|
||||
strategy raises `ValueError`. `pick` only considers webhooks that have a token — channel-
|
||||
follower and application-owned webhooks have none and can't be sent through, so they're
|
||||
skipped rather than picked. `send_any` sends through a picked existing webhook, **falling
|
||||
back to `get_or_create`** when the channel has none. On a dead pick, self-heal deletes that
|
||||
specific dead webhook (not the managed one) and recreates + retries once — unless the pick
|
||||
IS the managed webhook, in which case it goes through the normal `clear()` path. None of
|
||||
these three create or touch the store — they read live from the channel.
|
||||
|
||||
## What you inject
|
||||
|
||||
|
||||
Reference in New Issue
Block a user