2 Commits
4 changed files with 53 additions and 6 deletions
+5 -1
View File
@@ -203,7 +203,11 @@ func (s *Server) hangupVoWiFiAfter(deviceID, callID string, duration time.Durati
func (s *Server) callTransport(deviceID string) string {
if s.vowifi != nil {
if state, err := s.vowifi.State(deviceID); err == nil && state.Enabled {
// Enabled is only the desired card policy. Calls can use IMS only after
// registration has actually completed; otherwise keep using the modem's
// circuit-switched call path instead of routing into an unavailable IMS
// session.
if state, err := s.vowifi.State(deviceID); err == nil && state.IMSReady {
return "vowifi"
}
}
+13
View File
@@ -4,6 +4,7 @@ import (
"testing"
"vocat/internal/modem"
"vocat/internal/vowifi"
)
func TestParseCLCC(t *testing.T) {
@@ -28,3 +29,15 @@ func TestValidDialNumber(t *testing.T) {
}
}
}
func TestCallTransportRequiresIMSReady(t *testing.T) {
controller := &fakeVoWiFiController{state: vowifi.State{Enabled: true}}
server := &Server{vowifi: controller}
if got := server.callTransport("ec20"); got != "cellular" {
t.Fatalf("callTransport before IMS registration = %q, want cellular", got)
}
controller.state.IMSReady = true
if got := server.callTransport("ec20"); got != "vowifi" {
t.Fatalf("callTransport with IMS ready = %q, want vowifi", got)
}
}
+25 -5
View File
@@ -11,6 +11,7 @@ import (
"io"
"net/http"
"net/http/httptest"
"regexp"
"strconv"
"strings"
"sync"
@@ -30,6 +31,8 @@ const (
telegramMaxDialDuration = 10 * time.Minute
)
var telegramTokenInURLPattern = regexp.MustCompile(`bot[0-9]{5,20}:[A-Za-z0-9_-]{20,128}`)
type telegramRuntimeConfig struct {
Token string
ChatID string
@@ -146,6 +149,9 @@ func (bot *telegramBot) poll(ctx context.Context) {
updates, pollErr := bot.getUpdates(pollContext, config, offset, 5)
cancel()
if pollErr != nil {
if ctx.Err() != nil {
return
}
bot.warn("poll Telegram updates", pollErr)
if !waitTelegram(ctx, telegramPollInterval) {
return
@@ -970,7 +976,7 @@ func (bot *telegramBot) loadConfig(ctx context.Context) (telegramRuntimeConfig,
func (bot *telegramBot) call(ctx context.Context, config telegramRuntimeConfig, method string, payload any, result any) error {
base, err := validateTelegramAPIURL(ctx, config.BaseURL, config.Token, method)
if err != nil {
return err
return redactTelegramError(err, config.Token)
}
body, err := json.Marshal(payload)
if err != nil {
@@ -982,13 +988,13 @@ func (bot *telegramBot) call(ctx context.Context, config telegramRuntimeConfig,
}
request, err := http.NewRequestWithContext(ctx, http.MethodPost, base.String(), bytes.NewReader(body))
if err != nil {
return err
return redactTelegramError(err, config.Token)
}
request.Header.Set("Content-Type", "application/json")
request.Header.Set("User-Agent", "vocat-telegram-bot/1")
response, err := client.Do(request)
if err != nil {
return err
return redactTelegramError(err, config.Token)
}
defer response.Body.Close()
responseBody, err := io.ReadAll(io.LimitReader(response.Body, 2<<20))
@@ -1042,7 +1048,7 @@ func (bot *telegramBot) warn(message string, err error) {
return
}
now := time.Now()
text := err.Error()
text := redactTelegramText(err.Error(), "")
bot.logMu.Lock()
if text == bot.lastLogText && now.Sub(bot.lastLogTime) < time.Minute {
bot.logMu.Unlock()
@@ -1050,7 +1056,21 @@ func (bot *telegramBot) warn(message string, err error) {
}
bot.lastLogText, bot.lastLogTime = text, now
bot.logMu.Unlock()
bot.server.logger.Warn(message, "error", err)
bot.server.logger.Warn(message, "error", text)
}
func redactTelegramError(err error, token string) error {
if err == nil {
return nil
}
return errors.New(redactTelegramText(err.Error(), token))
}
func redactTelegramText(value, token string) string {
if strings.TrimSpace(token) != "" {
value = strings.ReplaceAll(value, token, "[REDACTED]")
}
return telegramTokenInURLPattern.ReplaceAllString(value, "bot[REDACTED]")
}
func parseTelegramCommand(text string) (string, string) {
+10
View File
@@ -2,6 +2,7 @@ package server
import (
"context"
"errors"
"strings"
"testing"
"time"
@@ -171,3 +172,12 @@ func TestTelegramExecutesInteractiveUSSDForConfiguredDevice(t *testing.T) {
}
}
}
func TestTelegramErrorsRedactBotTokens(t *testing.T) {
token := "1234567890:abcdefghijklmnopqrstuvwxyzABCDE"
err := errors.New(`Post "https://api.telegram.org/bot` + token + `/getUpdates": context canceled`)
redacted := redactTelegramError(err, token)
if strings.Contains(redacted.Error(), token) || !strings.Contains(redacted.Error(), "bot[REDACTED]") {
t.Fatalf("redacted error = %q", redacted)
}
}