Hard daily cap, no-flood shutdown, ctx-aware poller, double-image fix
Four related fixes after Pete flooded a channel and ignored Ctrl-C: 1. Global daily cap (posting.daily_cap_total, default 5): hard ceiling on posts across ALL channels in a rolling 24h window. Checked before the per-channel min-interval and burst-cap. 2. Shutdown no longer flushes the queue. Previous drainAll posted every remaining item with rate limits disabled — which was literally the flood. Replaced with dropOnShutdown that clears queues and logs the count. 3. Poller respects ctx mid-loop. pollOnceWithErr now takes ctx and bails between items, so Ctrl-C doesn't have to wait for ~30s of network per pending story before shutdown can complete. 4. Double-image fix. PostStory now reports imageSent; the queue clears ImageURL before retry so a text-send failure after a successful image upload doesn't re-post the image.
This commit is contained in:
@@ -323,12 +323,15 @@ func (c *Client) PostThreadedReply(channel string, rootEventID id.EventID, plain
|
||||
return err
|
||||
}
|
||||
|
||||
// PostStory sends a story to a channel. Returns the text event ID for reaction tracking.
|
||||
// If the story has a validated image, it's uploaded and sent as a separate m.image event first.
|
||||
func (c *Client) PostStory(channel string, story *PostableStory) (id.EventID, error) {
|
||||
// PostStory sends a story to a channel. Returns the text event ID for
|
||||
// reaction tracking and a flag indicating whether the m.image event was
|
||||
// successfully sent. Callers retrying after a failed text send MUST clear
|
||||
// the ImageURL on the next attempt if imageSent is true, otherwise the
|
||||
// image will be posted twice.
|
||||
func (c *Client) PostStory(channel string, story *PostableStory) (eventID id.EventID, imageSent bool, err error) {
|
||||
roomID, ok := c.channels[channel]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unknown channel: %s", channel)
|
||||
return "", false, fmt.Errorf("unknown channel: %s", channel)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
@@ -336,8 +339,10 @@ func (c *Client) PostStory(channel string, story *PostableStory) (id.EventID, er
|
||||
|
||||
// Send image first if present
|
||||
if story.ImageURL != "" {
|
||||
if err := c.sendImage(ctx, roomID, story.ImageURL); err != nil {
|
||||
slog.Warn("failed to send image, posting text only", "url", story.ImageURL, "err", err)
|
||||
if ierr := c.sendImage(ctx, roomID, story.ImageURL); ierr != nil {
|
||||
slog.Warn("failed to send image, posting text only", "url", story.ImageURL, "err", ierr)
|
||||
} else {
|
||||
imageSent = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,10 +357,10 @@ func (c *Client) PostStory(channel string, story *PostableStory) (id.EventID, er
|
||||
|
||||
resp, err := c.mx.SendMessageEvent(ctx, roomID, event.EventMessage, content)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("send message: %w", err)
|
||||
return "", imageSent, fmt.Errorf("send message: %w", err)
|
||||
}
|
||||
|
||||
return resp.EventID, nil
|
||||
return resp.EventID, imageSent, nil
|
||||
}
|
||||
|
||||
// sendImage downloads an image, uploads it to Matrix, and sends it as m.image.
|
||||
|
||||
Reference in New Issue
Block a user