the intake allowlist has to be a numeric chat id (V-637)
Two defects my own review found. The push half accepts @channelusername as a destination. The intake half cannot: an inbound update names its chat by numeric id, so that config would read the chat, match nothing, and answer none of it. Refused at NewPoller, which turns a dead reach into a line in the log. And getUpdates returns at most 100 updates per call, so one call was not the backlog. The skip loops, bounded at ten rounds rather than until empty, so an instance that keeps handing back a full batch cannot spin.
This commit is contained in:
@@ -14,6 +14,7 @@ package telegramsink
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -58,6 +59,13 @@ func NewPoller(s *Sink, turn Turn, correct Correct) (*Poller, error) {
|
|||||||
if turn == nil {
|
if turn == nil {
|
||||||
return nil, errors.New("telegramsink: intake needs a turn handler")
|
return nil, errors.New("telegramsink: intake needs a turn handler")
|
||||||
}
|
}
|
||||||
|
// The push half accepts @channelusername as a destination. The intake half
|
||||||
|
// cannot: an inbound update names its chat by numeric id, so an @-name would
|
||||||
|
// match nothing and the poller would read the chat and answer none of it.
|
||||||
|
// Refusing here is the difference between a boot error and a dead reach.
|
||||||
|
if strings.HasPrefix(strings.TrimSpace(s.cfg.ChatID), "@") {
|
||||||
|
return nil, fmt.Errorf("telegramsink: intake needs the numeric chat id, not %s", s.cfg.ChatID)
|
||||||
|
}
|
||||||
// The sink's transport already carries the relay. Only the timeout differs,
|
// The sink's transport already carries the relay. Only the timeout differs,
|
||||||
// and it has to clear the long poll.
|
// and it has to clear the long poll.
|
||||||
hc := &http.Client{
|
hc := &http.Client{
|
||||||
@@ -101,15 +109,26 @@ func (p *Poller) Run(ctx context.Context) {
|
|||||||
// stopped mattering, and a reminder set from it would land at the wrong time.
|
// stopped mattering, and a reminder set from it would land at the wrong time.
|
||||||
// Missing it is the safe direction.
|
// Missing it is the safe direction.
|
||||||
func (p *Poller) discardBacklog(ctx context.Context) {
|
func (p *Poller) discardBacklog(ctx context.Context) {
|
||||||
updates, err := p.getUpdates(ctx, 0)
|
// getUpdates returns at most 100 per call, so one call is not the queue. The
|
||||||
if err != nil {
|
// loop is bounded rather than "until empty": the timeout is 0, so an instance
|
||||||
// Not fatal. The offset stays 0, so the first real poll sees the backlog
|
// that keeps handing back a full batch would spin, and a thousand skipped
|
||||||
// and the messages below get answered late. Say so rather than hide it.
|
// messages is already a box that was down for a long time.
|
||||||
log.Printf("telegram intake: could not skip the backlog, old messages may be answered: %v", err)
|
skipped := 0
|
||||||
return
|
for range 10 {
|
||||||
|
updates, err := p.getUpdates(ctx, 0)
|
||||||
|
if err != nil {
|
||||||
|
// Not fatal. The offset stays where it was, so the first real poll sees
|
||||||
|
// what is left and answers it late. Say so rather than hide it.
|
||||||
|
log.Printf("telegram intake: could not skip the backlog, old messages may be answered: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
skipped += len(updates)
|
||||||
|
if len(updates) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(updates) > 0 {
|
if skipped > 0 {
|
||||||
log.Printf("telegram intake: skipped %d message(s) queued while the daemon was down", len(updates))
|
log.Printf("telegram intake: skipped %d message(s) queued while the daemon was down", skipped)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user