X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=fitbit%2Ffitbit.go;h=9f661d6637fc6170f675d0020d23cfcff2af9e09;hb=ad911fb5b8a17f238e6158b4f9479c5f8c428bff;hp=0f1a58375f7277247ba4ef2a4437d3824a824aa3;hpb=000f6f002f24e742f85ca20503a838c198637125;p=kraftakt.git diff --git a/fitbit/fitbit.go b/fitbit/fitbit.go index 0f1a583..9f661d6 100644 --- a/fitbit/fitbit.go +++ b/fitbit/fitbit.go @@ -23,7 +23,7 @@ var oauth2Config = &oauth2.Config{ ClientSecret: "@FITBIT_CLIENT_SECRET@", Endpoint: oauth2fitbit.Endpoint, RedirectURL: "https://fitbit-gfit-sync.appspot.com/fitbit/grant", - Scopes: []string{"activity"}, + Scopes: []string{"activity", "heartrate", "profile"}, } const csrfToken = "@CSRFTOKEN@" @@ -123,24 +123,24 @@ type Client struct { } func NewClient(ctx context.Context, fitbitUserID string, u *app.User) (*Client, error) { - tok, err := u.Token(ctx, "Fitbit") - if err != nil { - return nil, err - } - if fitbitUserID == "" { fitbitUserID = "-" } + c, err := u.OAuthClient(ctx, "Fitbit", oauth2Config) + if err != nil { + return nil, err + } + return &Client{ fitbitUserID: fitbitUserID, appUser: u, - client: oauth2Config.Client(ctx, tok), + client: c, }, nil } func (c *Client) ActivitySummary(t time.Time) (*ActivitySummary, error) { - url := fmt.Sprintf("https://api.fitbit.com/1/user/%s/activity/date/%s.json", + url := fmt.Sprintf("https://api.fitbit.com/1/user/%s/activities/date/%s.json", c.fitbitUserID, t.Format("2006-01-02")) res, err := c.client.Get(url) @@ -179,3 +179,43 @@ func (c *Client) Subscribe(ctx context.Context, collection string) error { return nil } + +type Profile struct { + Name string + Timezone *time.Location +} + +func (c *Client) Profile(ctx context.Context) (*Profile, error) { + res, err := c.client.Get("https://api.fitbit.com/1/user/-/profile.json") + if err != nil { + return nil, err + } + defer res.Body.Close() + + if res.StatusCode >= 400 { + data, _ := ioutil.ReadAll(res.Body) + log.Errorf(ctx, "reading profile failed: %s", data) + return nil, fmt.Errorf("HTTP %d error", res.StatusCode) + } + + var data struct { + User struct { + FullName string + OffsetFromUTCMillis int + Timezone string + } + } + if err := json.NewDecoder(res.Body).Decode(&data); err != nil { + return nil, err + } + + loc, err := time.LoadLocation(data.User.Timezone) + if err != nil { + loc = time.FixedZone("Fitbit preference", data.User.OffsetFromUTCMillis/1000) + } + + return &Profile{ + Name: data.User.FullName, + Timezone: loc, + }, nil +}