banner
Barry

Barry

偶尔摆烂,经常偶尔.
twitter
github
tg_channel
medium
email
steam_profiles

Keep running

Barry Running
Maintaining a daily exercise routine is a good habit. Recently, while browsing GitHub, I came across a project that can visualize our data from various sports apps on the front end. So, I decided to give it a try and set one up myself. Below, I will share how I implemented it, focusing mainly on the configuration of Keep.

Clone the main project to local#

The Running Page is an open-source project created by @yihong0618. Through this project, you can synchronize exercise data from multiple mainstream running platforms and automatically generate a map visualization running page. GitHub Pages allows for quick automatic deployment.

Project address: https://github.com/yihong0618/running_page
We can fork this repository to our own and clone it, or directly clone and upload it to our newly created repository.

Configure project files#

Note: The compressed package contains multiple files starting with a dot. On macOS, you need to use the shortcut "Command + shift + ." to show hidden files.

1. Find "gatsby-config.js" in the root directory and configure personalized options.#

pathPrefix: '/',   # If you need to use a custom domain, change this to /
siteMetadata: {
  siteTitle: 'Running Page',   # Site title
  siteUrl: 'https://running.domain.com',   # Site domain
  logo: 'https://q.qlogo.cn/headimg_dl?bs=qq&dst_uin=*********&spec=640',   # Top left avatar
  description: 'Just Do It',
  navLinks: [
    {
      name: 'Blog',   # Top right navigation bar
      url: 'https://blog.domain.com',
    },
  ],
},

2. Open the ".github" > "workflows" > "run_data_sync.yml" file, and modify the platform type and information. You can view the configuration information for different platforms on the documentation page.#

name: Run Data Sync

on:
  workflow_dispatch:
  schedule:
    - cron: "0 0 * * *"

env:
  # please change to your own config.
  RUN_TYPE: keep # support strava/nike/garmin/garmin_cn/keep/only_gpx/nike_to_strava/strava_to_garmin/strava_to_garmin_cn/garmin_to_strava/garmin_to_strava_cn, Please change the 'pass' it to your own
  ATHLETE: BarryYangi
  TITLE: Barry Running
  MIN_GRID_DISTANCE: 4 # change min distance here
  TITLE_GRID: Over 4km Runs # also here
  GITHUB_NAME: BarryYangi
  GITHUB_EMAIL: [email protected]

jobs:
  sync:
    name: Sync
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        
      - name: Set up Python
        uses: actions/setup-python@v1
        with:
          python-version: 3.7

      # from pdm
      - name: Set Variables
        id: set_variables
        run: |
          echo "PY=$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_OUTPUT
          echo "PIP_CACHE=$(pip cache dir)" >> $GITHUB_OUTPUT

      - name: Cache PIP
        uses: actions/cache@v2
        with:
          path: ${{ steps.set_variables.outputs.PIP_CACHE }}
          key: Ubuntu-pip-${{ steps.set_variables.outputs.PY }}
          
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
        if: steps.pip-cache.outputs.cache-hit != 'true'

      - name: Run sync Nike script
        if: env.RUN_TYPE == 'nike'
        run: |
          python scripts/nike_sync.py ${{ secrets.NIKE_REFRESH_TOKEN }}

      - name: Run sync Nike to Strava(Run with nike data backup and show with strava)
        if: env.RUN_TYPE == 'nike_to_strava'
        run: |
          python scripts/nike_to_strava_sync.py ${{ secrets.NIKE_REFRESH_TOKEN }} ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}

      - name: Run sync Keep script
        if: env.RUN_TYPE == 'keep'
        run: |
          python scripts/keep_sync.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx

      - name: Run sync Strava script
        if: env.RUN_TYPE == 'strava'
        run: |
          python scripts/strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}

      # for garmin if you want generate `tcx` you can add --tcx command in the args.
      - name: Run sync Garmin script
        if: env.RUN_TYPE == 'garmin'
        run: |
          python scripts/garmin_sync.py ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }}
        # If you only want to sync `type running` add args --only-run, default script is to sync all data (rides and runs).
        # python scripts/garmin_sync.py ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }} --only-run

      - name: Run sync Garmin CN script
        if: env.RUN_TYPE == 'garmin_cn'
        run: |
          python scripts/garmin_sync.py ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} --is-cn

      - name: Run sync Only GPX script
        if: env.RUN_TYPE == 'only_gpx'
        run: |
          python scripts/gpx_sync.py

      - name: Run sync Strava to Garmin(Run with strava(or others upload to strava) data backup in Garmin)
        if: env.RUN_TYPE == 'strava_to_garmin'
        run: |
          python scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }}

      - name: Run sync Strava to Garmin-cn(Run with strava(or others upload to strava) data backup in Garmin-cn)
        if: env.RUN_TYPE == 'strava_to_garmin_cn'
        run: |
          python scripts/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --is-cn

      - name: Run sync Garmin-cn to Strava(Run with Garmin data backup in Strava)
        if: env.RUN_TYPE == 'garmin_to_strava_cn'
        run: |
          python scripts/garmin_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_CN_EMAIL }} ${{ secrets.GARMIN_CN_PASSWORD }} --is-cn

      - name: Run sync Garmin to Strava(Run with Garmin data backup in Strava)
        if: env.RUN_TYPE == 'garmin_to_strava'
        run: |
          python scripts/garmin_to_strava_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_EMAIL }} ${{ secrets.GARMIN_PASSWORD }}

      - name: Run sync Tulipsport script
        if: env.RUN_TYPE == 'tulipsport'
        run: |
          python scripts/tulipsport_sync.py ${{ secrets.TULIPSPORT_TOKEN }} --with-gpx

      - name: Make svg GitHub profile
        if: env.RUN_TYPE != 'pass'
        run: |
          python scripts/gen_svg.py --from-db --title "${{ env.TITLE }}" --type github --athlete "${{ env.ATHLETE }}" --special-distance 10 --special-distance2 20 --special-color yellow --special-color2 red --output assets/github.svg --use-localtime --min-distance 0.5
          python scripts/gen_svg.py --from-db --title "${{ env.TITLE_GRID }}" --type grid --athlete "${{ env.ATHLETE }}" --output assets/grid.svg --special-color yellow --special-color2 red --special-distance 20 --special-distance2 40 --use-localtime --min-distance "${{ env.MIN_GRID_DISTANCE }}"
          python scripts/gen_svg.py --from-db --type circular --use-localtime
          python scripts/gen_svg.py --from-db --year $(date +"%Y")  --language zh_CN --title "$(date +"%Y") Running" --type github --athlete "${{ env.ATHLETE }}" --special-distance 10 --special-distance2 20 --special-color yellow --special-color2 red --output assets/github_$(date +"%Y").svg --use-localtime --min-distance 0.5
          
      - name: Deploy site
        uses: peaceiris/actions-gh-pages@v3
        with:
            github_token: ${{ secrets.MY_GIT_TOKEN }}
            publish_branch: vercel-pages
            publish_dir: .
            force_orphan: true
            # keep_files: true

Here, it is recommended to delete the remaining three workflow configuration yml files, as we do not need them. Later, we will configure the site on Vercel and then copy the content of my run_data_sync.yml file to overwrite this file.

3. Find the account information that needs to be completed for your corresponding platform#

For example, keep:

python scripts/keep_sync.py ${{ secrets.KEEP_MOBILE }} ${{ secrets.KEEP_PASSWORD }} --with-gpx

We need to be able to log into the Keep mobile account and password, which we will need later.

4. The Running Page uses Mapbox for map display, so you need to go to the Mapbox site to register a developer account.#

After logging in, select "Create a token" to create a token and complete the relevant information. After submission, you will receive a string of token information. Edit the "src" > "utils" > "const.js" file and replace your token in MAPBOX_TOKEN.

5. Save the file and push it to your git repository#

Git repository secrets configuration#

Go to your repository, click Settings -> Secrets and variables -> Actions -> New repository secret to create the following three secrets as shown in the picture
secrets

The first two items are the mobile account and password for Keep, and the last item is the GitHub token. If you don't have one, you can click your avatar -> Settings -> Developer settings -> Personal access tokens (classic) -> Generate new token.
When creating, you can check all permissions, and after creating, copy it down. This token will only appear once; after viewing, you will not be able to see it again. Then put this token into the secret in your repository.

Configure Vercel#

Go to our Vercel and register if you don't have an account, then bind it to our GitHub. After binding, click to import the newly created repository directly.
Then we go back to the GitHub repository and click Actions, and manually trigger a workflow as follows.
Actions

Wait for the workflow to finish running. If it is checked, it means there is no problem. At this point, we will find an additional vercel-pages branch. This branch will be used for deployment on Vercel. We go to the settings page of this project on Vercel and change the default deployment branch to vercel-pages, as shown in the picture:
image

After saving, we need to push once again to the vercel-pages branch for Vercel to truly apply it. We just need to re-execute the workflow we just operated on in the Actions page of the GitHub repository.

Wait for the workflow to finish running, and then return to the Vercel page to wait for the deployment to complete. You will find that the deployment branch has changed to vercel-pages.

Vercel domain binding#

If you want to share this page with your friends, this is certainly not elegant enough. If you have your own domain, you can bind it to your domain in the Domains option on the Vercel settings page.

End#

I hope this project brings us not just a simple project deployment experience, but also helps us develop a good exercise habit, which is the most important thing, and then record it so that we can trace back to the present in the future.
Just enjoy it.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.