Documentation
¶
Overview ¶
Package api contains the WW API client and data types.
Index ¶
- Constants
- Variables
- func ClampToWindow(start, end string) (clampedStart, clampedEnd, notice string, err error)
- func ComputeAllNutrition(logs []*DayLog) map[string]*DayNutrition
- func DateRange(start, end string) ([]string, error)
- func FetchLatestVersion() string
- type Client
- type DayLog
- type DayNutrition
- type DayPoints
- type DayStore
- type DayWater
- type DefaultPortion
- type FoodEntry
- type FoodStat
- type MacroBreakdown
- type MealStat
- type Meals
- type NutritionData
- type NutritionMap
- type RangeSummary
Constants ¶
const ( SourceWWFood = "WWFOOD" SourceMemberFood = "MEMBERFOOD" SourceWWVendorFood = "WWVENDORFOOD" SourceMemberRecipe = "MEMBERRECIPE" SourceWWRecipe = "WWRECIPE" SourceMemberFoodQuick = "MEMBERFOODQUICK" )
SourceType constants for food entry source types.
const APIWindowDays = 89
APIWindowDays is the WW my-day endpoint's hard backwards retention window in days. Verified empirically: 89 days back from today still returns 200, 90 days back returns 400. Older accounts hit the same wall — it's a server-side policy, not a per-account limit.
Variables ¶
var ErrOutOfWindow = errors.New("date outside WW retention window")
ErrOutOfWindow is returned by FetchDay when the WW my-day endpoint responds with HTTP 400 — the server enforces a ~89-day backwards retention window and rejects older dates outright. Callers can errors.Is(err, ErrOutOfWindow) to skip the day instead of aborting.
Functions ¶
func ClampToWindow ¶ added in v1.5.0
ClampToWindow checks start and end against the WW my-day endpoint's retention window and returns a usable range. If start is older than the window, it is clamped forward and a user-visible notice is returned. If end is also older than the window, no fetchable data exists and an error is returned. Callers that maintain a local DayStore should use LoadRange directly instead, which handles pre-window dates transparently.
func ComputeAllNutrition ¶
func ComputeAllNutrition(logs []*DayLog) map[string]*DayNutrition
ComputeAllNutrition derives aggregated nutrition from the embedded portion data in each log. No extra API calls required — all data comes from the my-day response.
func FetchLatestVersion ¶ added in v1.3.0
func FetchLatestVersion() string
FetchLatestVersion hits the GitHub Releases API and returns the latest published version tag (without the leading "v"), e.g. "1.2.3". Returns an empty string on any error so callers can treat it as optional.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is an authenticated WW API client.
func (*Client) FetchDay ¶
FetchDay retrieves the food log and points summary for a single date (YYYY-MM-DD).
func (*Client) FetchDayRaw ¶ added in v1.3.0
FetchDayRaw returns the raw JSON response body for a single date. Used for API inspection — run with --raw to see all available fields.
func (*Client) FetchWaterRange ¶ added in v1.12.0
FetchWaterRange returns water intake records for the given date range (inclusive). The returned map is keyed by date string (YYYY-MM-DD); dates with no water logged have no entry. Non-fatal: callers should treat an error as "no water data".
type DayLog ¶
type DayLog struct {
Date string
Meals Meals
Points DayPoints
Water *DayWater // nil when not fetched or no water logged
}
DayLog is the food log for a single date.
func LoadRange ¶ added in v1.5.0
func LoadRange(client *Client, ds DayStore, start, end string, offline bool) ([]*DayLog, []string, error)
LoadRange fetches every date in [start, end] from the WW API and, when ds is non-nil, from the local store.
Dates within the API retention window are fetched from the API and saved to the store (best-effort). Dates older than the window are served from the store only. Per-day 400 responses (ErrOutOfWindow) are skipped; the store is consulted as a fallback for those dates too.
When offline is true, no API calls are made — all dates are served from the local store. client may be nil in this case.
When a date fails with a non-window API error (network failure, server error), the store is consulted as a fallback and a notice is emitted rather than aborting. This allows the TUI and pipeline to serve archived data when the API is temporarily unavailable.
When ds is nil the behaviour is identical to the pre-store implementation: start is clamped to the window and a notice is emitted, or an error is returned if end is also outside the window.
Notices are user-visible info messages — print to stderr in pipeline mode or surface in the TUI status bar.
func (*DayLog) AllEntries ¶
AllEntries returns all food entries across all meal periods.
func (*DayLog) TotalPointsConsumed ¶ added in v1.5.0
TotalPointsConsumed sums PointsPrecise across all food entries, giving the true points spent that day regardless of how WW splits consumption between the daily target and the weekly allowance bucket. Points.DailyUsed from the API caps at DailyTarget — overflow flows silently into Points.WeeklyAllowanceUsed — so DailyUsed alone hides over-budget days.
type DayNutrition ¶
type DayNutrition struct {
Date string
Calories float64
Fat float64
SaturatedFat float64
Sodium float64
Carbs float64
Fiber float64
Sugar float64
AddedSugar float64
Protein float64
Alcohol float64
ItemCount int
}
DayNutrition holds aggregated nutritional totals for a single day.
type DayPoints ¶
type DayPoints struct {
Date string
DailyTarget float64
DailyUsed float64
DailyRemaining float64
WeeklyAllowance float64
WeeklyAllowanceRemaining float64
WeeklyAllowanceUsed float64
ActivityEarned float64
ActivityRemaining float64
WeeklyActivityEarned float64
VeggieServings float64
Weight float64
WeightUnit string
}
DayPoints holds the WW points summary for a single day.
type DayStore ¶ added in v1.8.0
DayStore is an optional local persistence layer for day logs. A nil DayStore disables persistence; LoadRange falls back to API-only behaviour identical to the pre-store implementation.
type DayWater ¶ added in v1.12.0
type DayWater struct {
Date string `json:"date"`
Glasses int `json:"glasses"`
FlOz float64 `json:"fl_oz"`
ServingFlOz float64 `json:"serving_fl_oz"`
}
DayWater holds water intake logged for a single day via the WW water tracker. Glasses is the number of 8-fl-oz glasses tapped in the app; FlOz is the total volume (Glasses × ServingFlOz). The WW API returns amount as glass count despite the unit field reading "fl oz" — multiply by ServingFlOz to get actual volume.
type DefaultPortion ¶
type DefaultPortion struct {
Name string `json:"name"`
Size float64 `json:"size"`
Nutrition NutritionMap `json:"nutrition"`
Points float64 `json:"points"`
}
DefaultPortion holds the canonical portion definition embedded in each tracked food entry.
type FoodEntry ¶
type FoodEntry struct {
ID string `json:"_id"`
EntryID string `json:"entryId"`
Name string `json:"name"`
PortionName string `json:"portionName"`
PortionSize float64 `json:"portionSize"`
SourceType string `json:"sourceType"`
TrackedDate string `json:"trackedDate"`
TimeOfDay string `json:"timeOfDay"`
ServingDesc string `json:"_servingDesc"`
DefaultPortion DefaultPortion `json:"defaultPortion"`
// PointsPrecise is the actual points charged to the budget for this entry.
// For ZeroPoint foods this is 0. Use this for all points calculations.
PointsPrecise float64 `json:"pointsPrecise"`
IsZPF bool `json:"isZPF"`
// PointsInfo.MaxPoints is the pre-ZPF calculated value. Only useful when
// you want to show "saved X points" for a ZPF food.
PointsInfo struct {
MaxPoints float64 `json:"maxPoints"`
} `json:"pointsInfo"`
}
FoodEntry represents a single tracked food item.
func (FoodEntry) Nutrition ¶
func (e FoodEntry) Nutrition() NutritionData
Nutrition computes scaled nutritional values for the tracked portion size.
type FoodStat ¶
type FoodStat struct {
Name string
Count int
TotalPts float64
AvgPts float64
TotalCals float64
AvgCals float64
}
FoodStat holds aggregate analytics for a single food across a date range.
type MacroBreakdown ¶
type MacroBreakdown struct {
ProteinPct float64
ProteinG float64
CarbsPct float64
CarbsG float64
FatPct float64
FatG float64
AlcoholPct float64
AlcoholG float64
}
MacroBreakdown holds the average daily grams and % of calories from each macronutrient.
func AvgMacroBreakdown ¶
func AvgMacroBreakdown(logs []*DayLog) MacroBreakdown
AvgMacroBreakdown computes the average daily macro distribution across all logs. Calories per gram: protein=4, carbs=4, fat=9, alcohol=7.
type Meals ¶
type Meals struct {
Morning []FoodEntry `json:"morning"`
Midday []FoodEntry `json:"midday"`
Evening []FoodEntry `json:"evening"`
Anytime []FoodEntry `json:"anytime"`
}
Meals groups food entries by meal period.
type NutritionData ¶
type NutritionData struct {
Name string
PortionName string
PortionSize float64
TrackedDate string
TimeOfDay string
Calories float64
Fat float64
SaturatedFat float64
Sodium float64
Carbs float64
Fiber float64
Sugar float64
AddedSugar float64
Protein float64
Alcohol float64
}
NutritionData holds calculated nutritional values for a single food entry.
type NutritionMap ¶
NutritionMap is a mixed-type map from the WW API — most values are floats but some keys (e.g. "isEstimatedSugar") are booleans. Only numeric values are kept.
func (*NutritionMap) UnmarshalJSON ¶
func (n *NutritionMap) UnmarshalJSON(data []byte) error
type RangeSummary ¶
type RangeSummary struct {
Days int
TotalItems int
AvgDailyPts float64
AvgDailyTarget float64
DaysUnderBudget int
DaysOverBudget int
AvgDailyCals float64
TotalActivityEarned float64
DaysWithActivity int
}
RangeSummary holds high-level statistics for a date range.
func ComputeRangeSummary ¶
func ComputeRangeSummary(logs []*DayLog) RangeSummary
ComputeRangeSummary derives high-level statistics across all day logs.