fix: improve Todoist user info API call with better logging and error handling
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 6s

This commit is contained in:
Play Life Bot
2026-01-02 15:45:54 +03:00
parent bd6dfd968c
commit bcea4b2bf5

View File

@@ -5848,38 +5848,76 @@ func getTodoistUserInfo(accessToken string) (struct {
Email string Email string
} }
req, err := http.NewRequest("POST", "https://api.todoist.com/sync/v9/sync", strings.NewReader("sync_token=*&resource_types=[\"user\"]")) // Формируем правильный запрос к Sync API
data := url.Values{}
data.Set("sync_token", "*")
data.Set("resource_types", `["user"]`)
req, err := http.NewRequest("POST", "https://api.todoist.com/sync/v9/sync", strings.NewReader(data.Encode()))
if err != nil { if err != nil {
log.Printf("Todoist API: failed to create request: %v", err)
return userInfo, err return userInfo, err
} }
req.Header.Set("Authorization", "Bearer "+accessToken) req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("User-Agent", "PlayLife") req.Header.Set("User-Agent", "PlayLife")
log.Printf("Todoist API: requesting user info from sync/v9/sync")
client := &http.Client{Timeout: 10 * time.Second} client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
log.Printf("Todoist API: request failed: %v", err)
return userInfo, fmt.Errorf("failed to get user info: %w", err) return userInfo, fmt.Errorf("failed to get user info: %w", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
bodyBytes, _ := io.ReadAll(resp.Body)
log.Printf("Todoist API: response status=%d, body=%s", resp.StatusCode, string(bodyBytes))
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body) return userInfo, fmt.Errorf("get user info failed (status %d): %s", resp.StatusCode, string(bodyBytes))
return userInfo, fmt.Errorf("get user info failed: %s", string(body))
} }
var result struct { // Парсим ответ - в Sync API user может быть объектом или массивом
User struct { var result map[string]interface{}
ID int64 `json:"id"` if err := json.Unmarshal(bodyBytes, &result); err != nil {
Email string `json:"email"` log.Printf("Todoist API: failed to parse JSON: %v, body: %s", err, string(bodyBytes))
} `json:"user"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return userInfo, fmt.Errorf("failed to decode user info: %w", err) return userInfo, fmt.Errorf("failed to decode user info: %w", err)
} }
userInfo.ID = result.User.ID log.Printf("Todoist API: parsed response keys: %v", getMapKeys(result))
userInfo.Email = result.User.Email
// Проверяем разные варианты структуры ответа
if userObj, ok := result["user"].(map[string]interface{}); ok {
// Один объект user
if id, ok := userObj["id"].(float64); ok {
userInfo.ID = int64(id)
}
if email, ok := userObj["email"].(string); ok {
userInfo.Email = email
}
} else if usersArr, ok := result["user"].([]interface{}); ok && len(usersArr) > 0 {
// Массив users, берем первый
if userObj, ok := usersArr[0].(map[string]interface{}); ok {
if id, ok := userObj["id"].(float64); ok {
userInfo.ID = int64(id)
}
if email, ok := userObj["email"].(string); ok {
userInfo.Email = email
}
}
} else {
log.Printf("Todoist API: user not found in response, available keys: %v", getMapKeys(result))
return userInfo, fmt.Errorf("user not found in response")
}
if userInfo.ID == 0 || userInfo.Email == "" {
log.Printf("Todoist API: incomplete user info: ID=%d, Email=%s", userInfo.ID, userInfo.Email)
return userInfo, fmt.Errorf("incomplete user info: ID=%d, Email=%s", userInfo.ID, userInfo.Email)
}
log.Printf("Todoist API: successfully got user info: ID=%d, Email=%s", userInfo.ID, userInfo.Email)
return userInfo, nil return userInfo, nil
} }