api

package
v1.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package api contains the WW API client and data types.

Index

Constants

View Source
const (
	SourceWWFood          = "WWFOOD"
	SourceMemberFood      = "MEMBERFOOD"
	SourceWWVendorFood    = "WWVENDORFOOD"
	SourceMemberRecipe    = "MEMBERRECIPE"
	SourceWWRecipe        = "WWRECIPE"
	SourceMemberFoodQuick = "MEMBERFOODQUICK"
)

SourceType constants for food entry source types.

View Source
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

View Source
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

func ClampToWindow(start, end string) (clampedStart, clampedEnd, notice string, err error)

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 DateRange

func DateRange(start, end string) ([]string, error)

DateRange returns a slice of YYYY-MM-DD strings from start to end inclusive.

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 New

func New(token, tld string) *Client

New creates an authenticated API client.

func (*Client) FetchDay

func (c *Client) FetchDay(date string) (*DayLog, error)

FetchDay retrieves the food log and points summary for a single date (YYYY-MM-DD).

func (*Client) FetchDayRaw added in v1.3.0

func (c *Client) FetchDayRaw(date string) ([]byte, error)

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

func (c *Client) FetchWaterRange(start, end string) (map[string]*DayWater, error)

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

func (d *DayLog) AllEntries() []FoodEntry

AllEntries returns all food entries across all meal periods.

func (*DayLog) TotalPointsConsumed added in v1.5.0

func (d *DayLog) TotalPointsConsumed() float64

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

type DayStore interface {
	Load(date string) (*DayLog, bool)
	Save(day *DayLog) error
}

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.

func TopFoods

func TopFoods(logs []*DayLog, limit int) []FoodStat

TopFoods returns food items sorted by total points then calories, up to limit items. Pass limit ≤ 0 to return all.

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 MealStat

type MealStat struct {
	Name    string
	Symbol  string
	AvgPts  float64
	AvgCals float64
}

MealStat holds average points and calories for a meal period across a date range.

func MealStats

func MealStats(logs []*DayLog) []MealStat

MealStats returns average daily points and calories for each meal period.

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

type NutritionMap map[string]float64

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL