Skip to content

Commit

Permalink
Prepare for release 4.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pe-st committed Mar 3, 2024
1 parent df58afe commit 54b52af
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 17 deletions.
33 changes: 23 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,11 @@ If you have many activities, you may find that this script crashes with an "Oper
You will need a little experience running things from the command line to use this script. That said, here are the usage details from the `--help` flag:

```
usage: gcexport.py [-h] [--version] [-v] [--username USERNAME]
[--password PASSWORD] [-c COUNT]
[-sd START_DATE] [-ed END_DATE]
[-e EXTERNAL] [-a ARGS]
[-f {gpx,tcx,original,json}] [-d DIRECTORY] [-s SUBDIR]
[-lp LOGPATH] [-u] [-ot] [--desc [DESC]] [-t TEMPLATE]
[-fp] [-sa START_ACTIVITY_NO] [-ex FILE]
[-ss DIRECTORY]
usage: gcexport.py [-h] [--version] [-v] [--username USERNAME] [--password PASSWORD]
[-c COUNT] [-sd START_DATE] [-ed END_DATE] [-e EXTERNAL] [-a ARGS]
[-f {gpx,tcx,original,json}] [-d DIRECTORY] [-s SUBDIR] [-lp LOGPATH]
[-u] [-ot] [--desc [DESC]] [-t TEMPLATE] [-fp] [-sa START_ACTIVITY_NO]
[-ex FILE] [-tf TYPE_FILTER] [-ss DIRECTORY]
Garmin Connect Exporter
Expand Down Expand Up @@ -95,12 +92,26 @@ optional arguments:
-sa START_ACTIVITY_NO, --start_activity_no START_ACTIVITY_NO
give index for first activity to import, i.e. skipping the newest activities
-ex FILE, --exclude FILE
JSON file with Array of activity IDs to exclude from download.
JSON file with array of activity IDs to exclude from download.
Format example: {"ids": ["6176888711"]}
-tf TYPE_FILTER, --type_filter TYPE_FILTER
comma-separated list of activity type IDs to allow. Format example: 3,9
-ss DIRECTORY, --session DIRECTORY
enable loading and storing SSO information from/to given directory
```

### Authentication

You have to authenticate with username and password, and possibly an MFA code, at least for an initial login.

The script is then using OAuth tokens (thanks to the [garth](https://github.com/matin/garth) library).
You can persist the OAuth token by giving a session directory, removing the need to provide username/password/MFA
for every script run.

But keep the persistent tokens safe; if somebody gets hold of your tokens, they might be able to
read all your data in Garmin Connect (e.g. your health data), maybe even change or delete it.


### Examples

- `python gcexport.py --count all`
Expand Down Expand Up @@ -184,7 +195,7 @@ For the history of this fork see the [CHANGELOG](CHANGELOG.md)

Contributions are welcome, see [CONTRIBUTING.md](CONTRIBUTING.md)

Contributors as of 2023-10 (Hope I didn't forget anyone,
Contributors as of 2024-03 (Hope I didn't forget anyone,
see also [Contributors](https://github.com/pe-st/garmin-connect-export/graphs/contributors)):

- Kyle Krafka @kjkjava
Expand Down Expand Up @@ -213,6 +224,8 @@ see also [Contributors](https://github.com/pe-st/garmin-connect-export/graphs/co
- @geraudloup
- @app4g
- Simon Ågren @agrensimon
- @embear
- Joe Timmerman @joetimmerman

## License

Expand Down
19 changes: 12 additions & 7 deletions gcexport.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
COOKIE_JAR = http.cookiejar.CookieJar()
OPENER = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(COOKIE_JAR), urllib.request.HTTPSHandler(debuglevel=0))

SCRIPT_VERSION = '4.3.0-Beta'
SCRIPT_VERSION = '4.3.0'

# This version here should correspond to what is written in CONTRIBUTING.md#python-3x-versions
MINIMUM_PYTHON_VERSION = (3, 8)
Expand Down Expand Up @@ -473,9 +473,9 @@ def parse_arguments(argv):
parser.add_argument('-sa', '--start_activity_no', type=int, default=1,
help='give index for first activity to import, i.e. skipping the newest activities')
parser.add_argument('-ex', '--exclude', metavar='FILE',
help='JSON file with Array of activity IDs to exclude from download. Format example: {"ids": ["6176888711"]}')
help='JSON file with array of activity IDs to exclude from download. Format example: {"ids": ["6176888711"]}')
parser.add_argument('-tf', '--type_filter',
help="comma-seperated list of activity type IDs to allow.")
help='comma-separated list of activity type IDs to allow. Format example: 3,9')
parser.add_argument('-ss', '--session', metavar='DIRECTORY',
help='enable loading and storing SSO information from/to given directory')
# fmt: on
Expand Down Expand Up @@ -973,6 +973,7 @@ def annotate_activity_list(activities, start, exclude_list, type_filter):
:param start: One-based index of the first non-skipped activity
(i.e. with 1 no activity gets skipped, with 2 the first activity gets skipped etc)
:param exclude_list: List of activity ids that have to be skipped explicitly
:param type_filter: list of activity types to include in the output
:return: List of action tuples
"""

Expand Down Expand Up @@ -1117,6 +1118,7 @@ def process_activity_item(item, number_of_items, device_dict, type_filter, activ
:param item: activity item tuple, see `annotate_activity_list()`
:param number_of_items: total number of items (for progress output)
:param device_dict: cache (dict) of already known devices
:param type_filter: list of activity types to include in the output
:param activity_type_name: lookup table for activity type descriptions
:param event_type_name: lookup table for event type descriptions
:param csv_filter: object encapsulating CSV file access
Expand All @@ -1140,10 +1142,11 @@ def process_activity_item(item, number_of_items, device_dict, type_filter, activ
print(f"({current_index}/{number_of_items}) [{actvty['activityId']}]")
return

# Action: Filtered out by typeID
# Action: Filtered out by typeId
if action == 'f':
# Display which entry we're skipping.
print(f"Filtering out due to typeID, {actvty['activityType']['typeId']} not in {type_filter} : Garmin Connect activity ", end='')
type_id = actvty['activityType']['typeId']
print(f"Filtering out due to type ID {type_id} not in {type_filter}: Garmin Connect activity ", end='')
print(f"({current_index}/{number_of_items}) [{actvty['activityId']}]")
return

Expand Down Expand Up @@ -1280,7 +1283,7 @@ def main(argv):

activities = fetch_activity_list(args, total_to_download)

type_filter = list(map(int,args.type_filter.split(','))) if args.type_filter is not None else None
type_filter = list(map(int, args.type_filter.split(','))) if args.type_filter is not None else None

action_list = annotate_activity_list(activities, args.start_activity_no, exclude_list, type_filter)

Expand All @@ -1297,7 +1300,9 @@ def main(argv):

# Process each activity.
for item in action_list:
process_activity_item(item, len(action_list), device_dict, type_filter, activity_type_name, event_type_name, csv_filter, args)
process_activity_item(
item, len(action_list), device_dict, type_filter, activity_type_name, event_type_name, csv_filter, args
)

logging.info('CSV file written.')

Expand Down

0 comments on commit 54b52af

Please sign in to comment.