Skip to content

Commit

Permalink
fix: added filter to the dump command (#15)
Browse files Browse the repository at this point in the history
* fix: added filter to the dump command

* docs: updated readme
  • Loading branch information
karl-cardenas-coding authored Jul 28, 2024
1 parent 7ea124b commit 4abbc62
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 11 deletions.
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ MyWhoop is a tool intended to help you take ownership of your Whoop data. You ca
- 🗄️ **Server**: Automatically download your Whoop data daily and save it to a local file or export it to a remote location.
- 📬 **Notifications**: Receive notifications when new data is available or when an error occurs.
- 💾 **Data Export**: Export your Whoop data to a remote location such as an S3 bucket.
- 🗂️ **Extensions**: Data exporters and notification services can be extended to support additional use cases.
- 🗂️ **Extensions**: Data exporters and notification services can be extended to support additional use cases. Check out the [Extensions](#extensions-️) section to learn more.
- 📦 **No Dependencies**: MyWhoop is available as a stand-alone binary or as a Docker image. No additional software is required to get started.

## Get Started 🚀
Expand Down Expand Up @@ -63,9 +63,31 @@ The dump command downloads **all your Whoop data** and saves it to a local file.
mywhoop dump
```

#### Flags

| Long Flag | Short Flag | Description | Required | Default |
|---|---|---|---|---|
| `--location` | `-l` |The location to save the Whoop data file. | No | `./data/` |
| `--filter` | `-f` | Specify a filter string to filter the data. For example to download all the data from January 2024 `start=2024-01-01T00:00:00.000Z&end=2024-01-31T00:00:00.000Z`. You can learn more about the filter syntax in the Whoop API [Pagination](https://developer.whoop.com/docs/developing/pagination) documentation. | No | `""` |

#### Filter

You can apply a filter to the data using the `--filter` flag. The filter flag expects a string that follows the Whoop API [Pagination](https://developer.whoop.com/docs/developing/pagination) filter syntax. A `start` value is required, the `end` value is optional. For example, to download all the data from January 2024, use the following filter string.

```bash
mywhoop dump --filter "start=2024-01-01T00:00:00.000Z&end=2024-01-31T00:00:00.000Z"
```
> [!TIP]
> Wrap the filter string in quotes to prevent the shell from interpreting the `&` character as a command separator.

You can omit the `end` value to download all the data from the specified `start` date to the current date. For example, to download all the data from March 2022 to the current date, use the following filter string.

```bash
mywhoop dump --filter "start=2022-03-01T00:00:00.000Z"
```

If you specify an invalid filter string, Whoop will normaly ignore the filter and return all the data.


> [!IMPORTANT]
Expand All @@ -80,6 +102,8 @@ The login command is used to authenticate with the Whoop API and save the authen
mywhoop login
```

#### Flags

| Long Flag | Short Flag |Description | Required | Default |
|---|--|--|---|---|
| `--no-auto-open` | `-n` |By default, the login command will automatically open a browser window to the Whoop login page. Use this flag to disable this behavior. | No | False |
Expand Down Expand Up @@ -120,3 +144,24 @@ mywhoop version
2024/07/06 10:50:29 INFO mywhoop v1.0.0
```


## Extensions 🗂️

MyWhoop supports extensions for data exporters and notification services. Exporters are used to export your Whoop data to a remote location, such as an S3 bucket or to a unique data store. Notification services are used to send notifications when new data is available or when an error occurs. Extensions are configured in the MyWhoop configuration file. For more information, refer to the [Configuration Reference](./docs/configuration_reference.md) section.


### Data Exporters

| Name | Description | Configuration |
|---|---| --- |
| File | This is the default exporter. The exporter saves the Whoop data to a local file. | [File Exporter](./docs/configuration_reference.md#file-export) |
| [AWS S3](https://aws.amazon.com/s3/) | The AWS S3 exporter saves the Whoop data to an S3 bucket. | [AWS S3 Exporter](./docs/configuration_reference.md#s3-export) |



### Notification Services

| Name | Description | Configuration |
|---|---| --- |
| stdout | The stdout notification is the default notification mechanism. Output is sent to the console. | [Stdout](./docs/configuration_reference.md#notification) |
| [Ntfy](https://ntfy.sh/) | Use the Ntfy notification service to send notifications to your phone or desktop. | [Ntfy](./docs/configuration_reference.md#ntfy) |
19 changes: 14 additions & 5 deletions cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import (
"github.com/spf13/cobra"
)

var dataLocation string
var (
dataLocation string
filter string
)

var dumpCmd = &cobra.Command{
Use: "dump",
Expand All @@ -31,6 +34,8 @@ var dumpCmd = &cobra.Command{

func init() {
dumpCmd.PersistentFlags().StringVarP(&dataLocation, "location", "l", "", "The location to dump the data to. Default is the current directory's data/ folder.")
dumpCmd.PersistentFlags().StringVarP(&filter, "filter", "f", "", "Provide a filter string to narrow down the data to download. For example, start=2024-01-01T00:00:00.000Z&end=2022-04-01T00:00:00.000Z")

rootCmd.AddCommand(dumpCmd)
}

Expand Down Expand Up @@ -79,6 +84,10 @@ func dump(ctx context.Context) error {
notificationMethod = std
}

if filter != "" {
slog.Info("Filtering data with:", "filter", filter)
}

data, err := user.GetUserProfileData(ctx, client, internal.DEFAULT_WHOOP_API_USER_DATA_URL, token.AccessToken, ua)
if err != nil {
internal.LogError(err)
Expand All @@ -103,7 +112,7 @@ func dump(ctx context.Context) error {

user.UserMesaurements = *measurements

sleep, err := user.GetSleepCollection(ctx, client, internal.DEFAULT_WHOOP_API_USER_SLEEP_DATA_URL, token.AccessToken, "", ua)
sleep, err := user.GetSleepCollection(ctx, client, internal.DEFAULT_WHOOP_API_USER_SLEEP_DATA_URL, token.AccessToken, filter, ua)
if err != nil {
internal.LogError(err)
notifyErr := notificationMethod.Publish(client, []byte(err.Error()), internal.EventErrors.String())
Expand All @@ -116,7 +125,7 @@ func dump(ctx context.Context) error {
sleep.NextToken = ""
user.SleepCollection = *sleep

recovery, err := user.GetRecoveryCollection(ctx, client, internal.DEFAULT_WHOOP_API_RECOVERY_DATA_URL, token.AccessToken, "", ua)
recovery, err := user.GetRecoveryCollection(ctx, client, internal.DEFAULT_WHOOP_API_RECOVERY_DATA_URL, token.AccessToken, filter, ua)
if err != nil {
internal.LogError(err)
notifyErr := notificationMethod.Publish(client, []byte(err.Error()), internal.EventErrors.String())
Expand All @@ -129,7 +138,7 @@ func dump(ctx context.Context) error {
recovery.NextToken = ""
user.RecoveryCollection = *recovery

workout, err := user.GetWorkoutCollection(ctx, client, internal.DEFAULT_WHOOP_API_WORKOUT_DATA_URL, token.AccessToken, "", ua)
workout, err := user.GetWorkoutCollection(ctx, client, internal.DEFAULT_WHOOP_API_WORKOUT_DATA_URL, token.AccessToken, filter, ua)
if err != nil {
internal.LogError(err)
notifyErr := notificationMethod.Publish(client, []byte(err.Error()), internal.EventErrors.String())
Expand All @@ -142,7 +151,7 @@ func dump(ctx context.Context) error {
workout.NextToken = ""
user.WorkoutCollection = *workout

cycle, err := user.GetCycleCollection(ctx, client, internal.DEFAULT_WHOOP_API_CYCLE_DATA_URL, token.AccessToken, "", ua)
cycle, err := user.GetCycleCollection(ctx, client, internal.DEFAULT_WHOOP_API_CYCLE_DATA_URL, token.AccessToken, filter, ua)
if err != nil {
internal.LogError(err)
notifyErr := notificationMethod.Publish(client, []byte(err.Error()), internal.EventErrors.String())
Expand Down
10 changes: 5 additions & 5 deletions internal/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@ func (u User) GetSleepCollection(ctx context.Context, client *http.Client, url,
urlWithFilters := url

if filters != "" {
slog.Debug("Sleep Filters", slog.String("Filters", filters))
urlWithFilters = url + filters
}

bo := generateBackoff()

for continueLoop {

slog.Info(("Requesting sleep collection from Whoop API"))
slog.Debug("URL", slog.String("URL", urlWithFilters))

if nextLoopUrl == "" {
Expand Down Expand Up @@ -185,7 +185,7 @@ func (u User) GetSleepCollection(ctx context.Context, client *http.Client, url,
if nextToken == "" {
continueLoop = false
} else {
nextLoopUrl = urlWithFilters + "nextToken=" + nextToken
nextLoopUrl = urlWithFilters + "&nextToken=" + nextToken
}

return nil
Expand Down Expand Up @@ -283,7 +283,7 @@ func (u User) GetRecoveryCollection(ctx context.Context, client *http.Client, ur
if nextToken == "" {
continueLoop = false
} else {
nextLoopUrl = urlWithFilters + "nextToken=" + nextToken
nextLoopUrl = urlWithFilters + "&nextToken=" + nextToken
}

return nil
Expand Down Expand Up @@ -381,7 +381,7 @@ func (u User) GetWorkoutCollection(ctx context.Context, client *http.Client, url
if nextToken == "" {
continueLoop = false
} else {
nextLoopUrl = urlWithFilters + "nextToken=" + nextToken
nextLoopUrl = urlWithFilters + "&nextToken=" + nextToken
}

return nil
Expand Down Expand Up @@ -475,7 +475,7 @@ func (u User) GetCycleCollection(ctx context.Context, client *http.Client, url,
if nextToken == "" {
continueLoop = false
} else {
nextLoopUrl = urlWithFilters + "nextToken=" + nextToken
nextLoopUrl = urlWithFilters + "&nextToken=" + nextToken
}

return nil
Expand Down

0 comments on commit 4abbc62

Please sign in to comment.