X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/1e2df788bbb17653a6df44acd41da2edb109d403..4c199e7d93b6a4529ed5956807911b5f6c5489a7:/telegram_api.go?ds=inline diff --git a/telegram_api.go b/telegram_api.go index 24f02ac..07d2bf1 100644 --- a/telegram_api.go +++ b/telegram_api.go @@ -52,11 +52,13 @@ func newTelegramAPI(base, token string) *TelegramAPI { // the Bot API asks for, or 0. func telegramRetryable(err error) (bool, time.Duration) { var network *TelegramNetworkError + if errors.As(err, &network) { return true, 0 } var answer *TelegramError + if errors.As(err, &answer) { return answer.Status == http.StatusTooManyRequests || answer.Status >= 500, answer.RetryAfter } @@ -70,6 +72,7 @@ func telegramRetryable(err error) (bool, time.Duration) { // tell this, so it is not a refusal. func telegramRejected(err error) bool { var answer *TelegramError + return errors.As(err, &answer) && answer.Refused && (answer.Status == http.StatusBadRequest || answer.Status == http.StatusNotFound) } @@ -89,6 +92,7 @@ type TelegramAPI struct { // messages are asked for. func (b *TelegramAPI) GetUpdates(ctx context.Context, offset int64) ([]TelegramUpdate, error) { var updates []TelegramUpdate + err := b.call(ctx, telegramPollTimeout, "getUpdates", map[string]any{ "offset": offset, "timeout": telegramPollSeconds, @@ -155,6 +159,7 @@ func (b *TelegramAPI) call(ctx context.Context, timeout time.Duration, method st } request.Header.Set("Content-Type", "application/json") + response, err := b.http.Do(request) if err != nil { return b.networkError("no answer", err, timeout) @@ -163,10 +168,11 @@ func (b *TelegramAPI) call(ctx context.Context, timeout time.Duration, method st data, err := io.ReadAll(io.LimitReader(response.Body, telegramAnswerBytes)) err = errors.Join(err, response.Body.Close()) if err != nil { - return b.networkError("the answer broke off", err, timeout) + return b.networkError("answer cut off", err, timeout) } var answer TelegramAnswer + err = json.Unmarshal(data, &answer) if err != nil && response.StatusCode != http.StatusOK { return &TelegramError{ @@ -176,7 +182,7 @@ func (b *TelegramAPI) call(ctx context.Context, timeout time.Duration, method st } if err != nil { - return b.networkError("the answer is not valid JSON", err, timeout) + return b.networkError("invalid JSON", err, timeout) } if !answer.OK { @@ -194,7 +200,7 @@ func (b *TelegramAPI) call(ctx context.Context, timeout time.Duration, method st err = json.Unmarshal(answer.Result, result) if err != nil { - return b.networkError("the result is not valid", err, timeout) + return b.networkError("invalid result", err, timeout) } return nil @@ -221,6 +227,7 @@ func (b *TelegramAPI) networkError(what string, err error, timeout time.Duration // cause is kept. func (b *TelegramAPI) redact(err error) string { var urlError *url.Error + if errors.As(err, &urlError) { err = urlError.Err } @@ -240,10 +247,10 @@ func (e *TelegramNetworkError) Error() string { } // TelegramError is an answer of the Bot API that tells of a failure. Its text -// gives the HTTP status and the description, such as "Telegram answered 502 Bad -// Gateway". RetryAfter is the wait that the Bot API asks for after HTTP 429. -// Refused tells that the answer is a Bot API answer with ok false, not a page -// of a proxy or of a server error. +// gives the HTTP status and the description, such as "502 Bad Gateway". +// RetryAfter is the wait that the Bot API asks for after HTTP 429. Refused +// tells that the answer is a Bot API answer with ok false, not a page of a +// proxy or of a server error. type TelegramError struct { Status int Description string @@ -252,7 +259,7 @@ type TelegramError struct { } func (e *TelegramError) Error() string { - return fmt.Sprintf("Telegram answered %d %s", e.Status, e.Description) + return fmt.Sprintf("%d %s", e.Status, e.Description) } // TelegramUpdate is one update of getUpdates. Message is nil for the kinds of