feat: enhance Safew error handling and polling mechanism

- Added error_msg field to safewAPIResponse for better error descriptions.
- Updated safewErrorDescription function to include error_msg in the output.
- Introduced a new test to verify that error messages are included in Safew error descriptions.
- Improved the polling mechanism in the Watcher to handle conflicts and ensure no overlapping polls occur.
This commit is contained in:
2026-08-15 01:07:01 +08:00
parent bd8a9ff96d
commit e369f398d8
4 changed files with 201 additions and 28 deletions
+19 -5
View File
@@ -7,6 +7,7 @@ import (
"io"
"net/http"
"strings"
"time"
)
const safewAPIBase = "https://api.safew.bot"
@@ -29,6 +30,7 @@ type safewMessage struct {
type safewAPIResponse struct {
OK bool `json:"ok"`
Description string `json:"description"`
ErrorMsg string `json:"error_msg"`
}
func (s *SafeWSender) Type() string { return "safew" }
@@ -112,17 +114,22 @@ func (e *SafewAuthError) Error() string {
return e.Description
}
var safewLongPollClient = &http.Client{Timeout: 45 * time.Second}
func (s *SafeWSender) PollGroupChats(token string, offset int64, timeout int) ([]SafewChat, int64, error) {
token = strings.TrimSpace(token)
if token == "" {
return nil, offset, fmt.Errorf("safew: token is required")
}
reqBody, _ := json.Marshal(map[string]any{
payload := map[string]any{
"timeout": timeout,
"offset": offset,
"limit": 100,
})
resp, err := http.Post(s.methodURL(token, "getUpdates"), "application/json", bytes.NewReader(reqBody))
}
if offset > 0 {
payload["offset"] = offset
}
reqBody, _ := json.Marshal(payload)
resp, err := safewLongPollClient.Post(s.methodURL(token, "getUpdates"), "application/json", bytes.NewReader(reqBody))
if err != nil {
return nil, offset, fmt.Errorf("safew getUpdates: %w", err)
}
@@ -183,7 +190,14 @@ func safewErrorDescription(body []byte) string {
if err := json.Unmarshal(body, &api); err != nil {
return strings.TrimSpace(string(body))
}
return api.Description
switch {
case api.Description != "" && api.ErrorMsg != "":
return api.Description + ": " + api.ErrorMsg
case api.ErrorMsg != "":
return api.ErrorMsg
default:
return api.Description
}
}
func escapeMarkdownV2(s string) string {