X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/48d7bce28b18ecef4c52c98821675605464cecb9..add3cf6416e33c24331fd1e90e99284f44d2aae2:/telegram_api.go diff --git a/telegram_api.go b/telegram_api.go index a04b2fa..8f78387 100644 --- a/telegram_api.go +++ b/telegram_api.go @@ -15,25 +15,33 @@ import ( ) const ( - // telegramPollSeconds is how long one getUpdates call waits for an - // update. - telegramPollSeconds = 50 + // telegramUpdateWaitTimeout is how long one getUpdates call waits for + // an update. + telegramUpdateWaitTimeout = 50 * time.Second - // telegramPollSlack is how much longer than telegramPollSeconds a + // telegramPollSlack is how much longer than telegramUpdateWaitTimeout a // getUpdates call can take before the bot gives it up. telegramPollSlack = 20 * time.Second // telegramPollTimeout is how long one getUpdates call can take. - telegramPollTimeout = telegramPollSeconds*time.Second + telegramPollSlack - - // telegramSendTimeout is how long a sendMessage, sendRichMessage, or - // sendChatAction call can take. A connection that stops without a - // close, such as after a network change, then fails the call, and the - // sender tries again, instead of a wait until TCP gives up. The client - // has no timeout of its own, because the long poll of getUpdates needs - // a longer limit. + telegramPollTimeout = telegramUpdateWaitTimeout + telegramPollSlack + + // telegramSendTimeout is how long a sendMessage or sendRichMessage call + // can take. A connection that stops without a close, such as after a + // network change, then fails the call, and the sender tries again, + // instead of a wait until TCP gives up. The client has no timeout of + // its own, because the long poll of getUpdates needs a longer limit. telegramSendTimeout = 30 * time.Second + // telegramFileLookupTimeout is the longest wait for image file details. + telegramFileLookupTimeout = 30 * time.Second + + // telegramImageDownloadTimeout is the longest wait for image bytes. + telegramImageDownloadTimeout = 30 * time.Second + + // telegramTypingTimeout is the longest wait to show the typing action. + telegramTypingTimeout = 30 * time.Second + // telegramAnswerBytes is the most bytes of one answer of the Bot API. telegramAnswerBytes = 16 << 20 ) @@ -84,15 +92,15 @@ type TelegramAPI struct { http *http.Client } -// GetUpdates waits for the updates from offset on, up to telegramPollSeconds, -// and returns them. Telegram forgets each update before offset. Only new -// messages are asked for. +// GetUpdates waits for the updates from offset on, up to +// telegramUpdateWaitTimeout, and returns them. Telegram forgets each update +// before offset. Only new 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, + "timeout": int(telegramUpdateWaitTimeout / time.Second), "allowed_updates": []string{"message"}, }, &updates) @@ -107,7 +115,7 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err Size int64 `json:"file_size"` } - err = b.call(ctx, telegramSendTimeout, "getFile", map[string]any{"file_id": id}, &file) + err = b.call(ctx, telegramFileLookupTimeout, "getFile", map[string]any{"file_id": id}, &file) if err != nil { return nil, fmt.Errorf("get image file: %w", err) } @@ -120,7 +128,7 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err return nil, errors.New("invalid image file path") } - ctx, cancel := context.WithTimeout(ctx, telegramSendTimeout) + ctx, cancel := context.WithTimeout(ctx, telegramImageDownloadTimeout) defer cancel() request, err := http.NewRequestWithContext(ctx, http.MethodGet, b.base+"/file/bot"+b.token+"/"+file.Path, nil) @@ -130,13 +138,13 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err response, err := b.http.Do(request) if err != nil { - return nil, b.networkError("image download failed", err, telegramSendTimeout) + return nil, b.networkError("image download failed", err, telegramImageDownloadTimeout) } defer func() { closeErr := response.Body.Close() if closeErr != nil { - err = errors.Join(err, b.networkError("close image download", closeErr, telegramSendTimeout)) + err = errors.Join(err, b.networkError("close image download", closeErr, telegramImageDownloadTimeout)) } }() @@ -149,7 +157,7 @@ func (b *TelegramAPI) GetImage(ctx context.Context, id string) (data []byte, err data, err = io.ReadAll(io.LimitReader(response.Body, imageMaxBytes+1)) if err != nil { - return nil, b.networkError("image cut off", err, telegramSendTimeout) + return nil, b.networkError("image cut off", err, telegramImageDownloadTimeout) } if len(data) > imageMaxBytes { @@ -189,9 +197,10 @@ func (b *TelegramAPI) SendRichMessage(ctx context.Context, chat int64, markdown } // SendTyping shows the typing action in chat for about five seconds. A call -// that takes longer than telegramSendTimeout fails with a TelegramNetworkError. +// that takes longer than telegramTypingTimeout fails with a +// TelegramNetworkError. func (b *TelegramAPI) SendTyping(ctx context.Context, chat int64) error { - return b.call(ctx, telegramSendTimeout, "sendChatAction", map[string]any{ + return b.call(ctx, telegramTypingTimeout, "sendChatAction", map[string]any{ "chat_id": chat, "action": "typing", }, nil)