{"id":13492046,"url":"https://github.com/yihong0618/running_page","last_synced_at":"2025-05-13T17:11:29.241Z","repository":{"id":37096121,"uuid":"296233312","full_name":"yihong0618/running_page","owner":"yihong0618","description":"Make your own running home page","archived":false,"fork":false,"pushed_at":"2025-05-13T00:47:38.000Z","size":86240,"stargazers_count":3999,"open_issues_count":48,"forks_count":1184,"subscribers_count":45,"default_branch":"master","last_synced_at":"2025-05-13T01:34:55.957Z","etag":null,"topics":["adidas","club-nike","data-analysis","data-visualization","garmin","garmin-watch","github-secret","gpx","mapbox","nike","strava","vercel"],"latest_commit_sha":null,"homepage":"https://running-page.vercel.app","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yihong0618.png","metadata":{"files":{"readme":"README-CN.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-09-17T05:59:22.000Z","updated_at":"2025-05-13T00:47:43.000Z","dependencies_parsed_at":"2023-02-18T17:31:06.256Z","dependency_job_id":"db8096e2-6106-4151-ad39-e4fd7b6e3e4d","html_url":"https://github.com/yihong0618/running_page","commit_stats":{"total_commits":780,"total_committers":126,"mean_commits":6.190476190476191,"dds":0.5474358974358975,"last_synced_commit":"3a973b8db4d1599b69a57babadd15ae40e751709"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yihong0618%2Frunning_page","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yihong0618%2Frunning_page/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yihong0618%2Frunning_page/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yihong0618%2Frunning_page/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yihong0618","download_url":"https://codeload.github.com/yihong0618/running_page/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253990470,"owners_count":21995774,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adidas","club-nike","data-analysis","data-visualization","garmin","garmin-watch","github-secret","gpx","mapbox","nike","strava","vercel"],"created_at":"2024-07-31T19:01:02.596Z","updated_at":"2025-05-13T17:11:24.228Z","avatar_url":"https://github.com/yihong0618.png","language":"Python","funding_links":[],"categories":["Python","前端开发框架及项目","Data Analysis \u0026 Visualization"],"sub_categories":["React工具库"],"readme":"## Note\n\n1. clone or Fork before vercel 404 need to pull the latest code\n2. python3(python) in README means python3 python\n3. use v2.0 need change vercel setting from gatsby to vite\n4. 2023.09.26 garmin need secret_string(and in Actions) get\n    \n    ```bash\n      python run_page/get_garmin_secret.py ${email} ${password}\n      # if cn\n      python run_page/get_garmin_secret.py ${email} ${password} --is-cn\n    ```\n\n5. 2024.09.29: Added `Elevation Gain` field, If you forked the project before this update, please run the following command:\n    - To resolve errors: `sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: activities.elevation_gain`\n    - If you don't have a local environment, set `RUN_TYPE` to `db_updater` in the `.github/workflows/run_data_sync.yml` file once then change back. \n\n    ```bash\n      python run_page/db_updater.py\n    ```\n    - For old data: To include `Elevation Gain` for past activities, perform a full reimport. \n    - To show the 'Elevation Gain' column, modify `SHOW_ELEVATION_GAIN` in `src/utils/const.ts`\n    - note: `Elevation Gain` may be inaccurate. You can use Strava's \"Correct Elevation\" or Garmin's \"Elev Corrections\" feature for more precise data. \n\n![running_page](https://socialify.git.ci/yihong0618/running_page/image?description=1\u0026font=Inter\u0026forks=1\u0026issues=1\u0026language=1\u0026logo=https%3A%2F%2Fraw.githubusercontent.com%2Fshaonianche%2Fgallery%2Fmaster%2Frunning_page%2Frunning_page_logo_150*150.jpg\u0026owner=1\u0026pulls=1\u0026stargazers=1\u0026theme=Light)\n\n# [这里是白银越野赛全部 21 位逝者的故事](https://github.com/yihong0618/running_page/issues/135)\n\nR.I.P. 希望大家都能健康顺利的跑过终点，逝者安息。\n\n# [打造个人跑步主页](https://yihong.run/running)\n\n[English](README.md) | 简体中文 | [Wiki](https://wiki.mfydev.run/)\n\n\u003cdetails\u003e\n\u003csummary\u003eGIF 展示\u003c/summary\u003e\n\n\u003cbr\u003e\n\n![running_page](https://user-images.githubusercontent.com/15976103/98808834-c02f1d80-2457-11eb-9a7c-70e91faa5e30.gif)\n\n\u003c/details\u003e\n\n## [大家的跑步主页展示](https://github.com/yihong0618/running_page/issues/12)\n\n\u003cdetails\u003e\n\u003csummary\u003eRunning page runners\u003c/summary\u003e\n\n\u003cbr\u003e\n\n| Runner                                            | page                                           | App         |\n| ------------------------------------------------- | ---------------------------------------------- | ----------- |\n| [zhubao315](https://github.com/zhubao315)         | \u003chttps://zhubao315.github.io/running\u003e          | Strava      |\n| [shaonianche](https://github.com/shaonianche)     | \u003chttps://run.duanfei.org\u003e                      | Strava      |\n| [yihong0618](https://github.com/yihong0618)       | \u003chttps://yihong.run\u003e                           | Nike        |\n| [superleeyom](https://github.com/superleeyom)     | \u003chttps://running.leeyom.top\u003e                   | Strava        |\n| [geekplux](https://github.com/geekplux)           | \u003chttps://activities.geekplux.com\u003e              | Nike        |\n| [guanlan](https://github.com/guanlan)             | \u003chttps://grun.vercel.app\u003e                      | Strava      |\n| [tuzimoe](https://github.com/tuzimoe)             | \u003chttps://run.tuzi.moe\u003e                         | Nike        |\n| [ben_29](https://github.com/ben-29)               | \u003chttps://running.ben29.xyz\u003e                    | Strava      |\n| [kcllf](https://github.com/kcllf)                 | \u003chttps://running-tau.vercel.app\u003e               | Garmin-cn   |\n| [mq](https://github.com/MQ-0707)                  | \u003chttps://running-iota.vercel.app\u003e              | Keep        |\n| [zhaohongxuan](https://github.com/zhaohongxuan)   | \u003chttps://zhaohongxuan.github.io/workouts\u003e      | Strava      |\n| [yvetterowe](https://github.com/yvetterowe)       | \u003chttps://run.haoluo.io\u003e                        | Strava      |\n| [love-exercise](https://github.com/KaiOrange)     | \u003chttps://run.kai666666.top\u003e                    | Keep        |\n| [zstone12](https://github.com/zstone12)           | \u003chttps://running-page.zstone12.vercel.app\u003e     | Keep        |\n| [Lax](https://github.com/Lax)                     | \u003chttps://lax.github.io/running\u003e                | Keep        |\n| [lusuzi](https://github.com/lusuzi)               | \u003chttps://running.lusuzi.vercel.app\u003e            | Nike        |\n| [wh1994](https://github.com/wh1994)               | \u003chttps://run4life.fun\u003e                         | Garmin      |\n| [liuyihui](https://github.com/YiHui-Liu)          | \u003chttps://run.foolishfox.cn\u003e                    | Keep        |\n| [sunyunxian](https://github.com/sunyunxian)       | \u003chttps://sunyunxian.github.io/running_page\u003e    | Strava      |\n| [AhianZhang](https://github.com/AhianZhang)       | \u003chttps://running.ahianzhang.com\u003e               | Nike        |\n| [L1cardo](https://github.com/L1cardo)             | \u003chttps://run.licardo.cn\u003e                       | Nike        |\n| [luckylele666](https://github.com/luckylele666)   | \u003chttps://0000928.xyz\u003e                          | Strava      |\n| [MFYDev](https://github.com/MFYDev)               | \u003chttps://mfydev.run\u003e                           | Garmin-cn   |\n| [Oysmart](https://github.com/oysmart)             | \u003chttps://run.ouyang.wang\u003e                      | Garmin-cn   |\n| [Eished](https://github.com/eished)               | \u003chttps://run.iknow.fun\u003e                        | Keep        |\n| [Liuxin](https://github.com/liuxindtc)            | \u003chttps://liuxin.run\u003e                           | Nike        |\n| [loucx](https://github.com/loucx)                 | \u003chttps://loucx.github.io/running\u003e              | Nike        |\n| [winf42](https://github.com/winf42)               | \u003chttps://winf42.github.io\u003e                     | Garmin-cn   |\n| [sun0225SUN](https://github.com/sun0225SUN)       | \u003chttps://run.sunguoqi.com\u003e                     | Nike        |\n| [Zhan](https://www.zlog.in/about)                 | \u003chttps://run.zlog.in\u003e                          | Nike        |\n| [Dennis](https://run.domon.cn)                    | \u003chttps://run.domon.cn\u003e                         | Garmin-cn   |\n| [hanpei](https://running.nexts.top)               | \u003chttps://running.nexts.top\u003e                    | Garmin-cn   |\n| [liugezhou](https://github.com/liugezhou)         | \u003chttps://run.liugezhou.online\u003e                 | Strava      |\n| [zhubao315](https://github.com/zhubao315)         | \u003chttps://zhubao315.github.io/running\u003e          | Strava      |\n| [Jason Tan](https://github.com/Jason-cqtan)       | \u003chttps://jason-cqtan.github.io/running_page\u003e   | Nike        |\n| [Conge](https://github.com/conge)                 | \u003chttps://conge.github.io/running_page\u003e         | Strava      |\n| [cvvz](https://github.com/cvvz)                   | \u003chttps://cvvz.github.io/running\u003e               | Strava      |\n| [zHElEARN](https://github.com/zHElEARN)           | \u003chttps://workouts.zhelearn.com\u003e                | Strava      |\n| [Rhfeng](https://sport.frh.life)                  | \u003chttps://sport.frh.life\u003e                       | Garmin-cn   |\n| [Ym9i](https://github.com/Ym9i)                   | \u003chttps://bobrun.vercel.app/\u003e                   | Strava      |\n| [jianchengwang](https://github.com/jianchengwang) | \u003chttps://jianchengwang.github.io/running_page\u003e | Suunto      |\n| [fxbin](https://github.com/fxbin)                 | \u003chttps://fxbin.github.io/sport-records/\u003e       | Keep        |\n| [shensl4499](https://github.com/shensl4499)       | \u003chttps://waner.run\u003e                            | codoon      |\n| [haowei93](https://github.com/haowei93)           | \u003chttps://running-fun.eu.org\u003e                   | gpx         |\n| [stevenash0822](https://github.com/stevenash0822) | \u003chttps://run.imangry.xyz/\u003e                     | Strava      |\n| [Vint](https://github.com/VintLin)                | \u003chttps://vinton.store/Running/\u003e                | Keep        |\n| [Muyids](https://github.com/muyids)               | \u003chttps://muyids.github.io/running\u003e             | Garmin-cn   |\n| [Gao Hao](https://github.com/efish2002)           | \u003chttps://efish2002.github.io/running_page/\u003e    | Garmin-cn   |\n| [Jinlei](https://github.com/iamjinlei0312)        | \u003chttps://jinlei.run/\u003e                          | 咕咚        |\n| [Ray Wang](https://github.com/raywangsy)          | \u003chttps://run.raywang.pro/\u003e                     | Garmin      |\n| [RealTiny656](https://github.com/tiny656)         | \u003chttps://tiny656.github.io/running_page/\u003e      | JoyRun      |\n| [EINDEX](https://github.com/eindex)               | \u003chttps://workouts.eindex.me/\u003e                  | Strava/Nike |\n| [Melt](https://github.com/fpGHwd)                 | \u003chttps://running.autove.dev/\u003e                  | Strava      |\n| [deepinwine](https://github.com/deepinwine)       | \u003chttps://deepin.autove.dev/\u003e                   | Garmin-cn   |\n| [Jeffggmm](https://github.com/Jeffggmm)           | \u003chttps://jeffggmm.github.io/workouts_page/\u003e    | Garmin      |\n| [s1smart](https://github.com/s1smart)             | \u003chttps://s1smart.github.io/running_page/\u003e      | Strava      |\n| [Ryan](https://github.com/85Ryan)                 | \u003chttps://85ryan.github.io/gooorun/\u003e            | Strava      |\n| [PPZ](https://github.com/8824PPZ)                 | \u003chttps://run.dudubbbbbbbbb.top/\u003e               | Strava      |\n| [Yer1k](https://github.com/Yer1k)                 | \u003chttps://running.yer1k.com/\u003e                   | Strava      |\n| [AlienVision](https://github.com/weaming)         | \u003chttps://run.drink.cafe/\u003e                      | Strava      |\n| [Vensent](https://github.com/Vensent)             | \u003chttps://vensent.github.io/workouts_page/\u003e     | Garmin      |\n| [Zeonsing](https://github.com/NoonieBao)          | \u003chttps://run.jogzeal.com/\u003e                     | Coros       |\n| [yaoper](https://github.com/yaoper)               | \u003chttps://running.yaoper.cn\u003e                    | codoon      |\n| [NoZTurn](https://github.com/NoZTurn)             | \u003chttps://run.jiangkai.org\u003e                     | Strava      |\n| [laqieer](https://github.com/laqieer)             | \u003chttps://laqieer.github.io/running_page/\u003e      | Strava      |\n| [Guoxin](https://github.com/guoxinl)              | \u003chttps://running.guoxin.space/\u003e                | Strava      |\n| [Darren](https://github.com/Flavored4179)         | \u003chttps://run.wdoc.top/\u003e                        | tcx         |\n| [Evan](https://github.com/LinghaoChan)            | \u003chttps://github.com/LinghaoChan/running\u003e       | Keep        |\n| [Shuqi](https://github.com/zhufengme)            | \u003chttps://runner-shuqi.devlink.cn/\u003e              | Garmin      |\n| [shugoal](https://github.com/shugoal)            | \u003chttps://shugoal.github.io/wk-shu/\u003e             | Garmin      |\n\u003c/details\u003e\n\n## 它是怎么工作的\n\n![image](https://github.com/yihong0618/running_page/assets/15976103/85d8d59d-2639-431e-8406-9d818afbd4ab)\n\n## 特性\n\n1. GitHub Actions 自动同步跑步数据，生成展示页面\n2. 支持 Vercel（推荐）和 GitHub Pages 自动部署\n3. React Hooks\n4. Mapbox 进行地图展示\n5. Nike、Strava、佳明（佳明中国）及 Keep 等，自动备份 GPX 数据，方便备份及上传到其它软件\n\n\u003e 因为数据存在 gpx 和 data.db 中，理论上支持几个软件一起，你可以把之前各类 App 的数据都同步到这里（建议本地同步，之后 Actions 选择正在用的 App）\n\n\u003e 如果你不想公开数据，可以选择 `Strava` 的模糊处理，或 `private` 仓库。\n\n\u003cdetails\u003e\n\u003csummary\u003e缩放地图彩蛋\u003c/summary\u003e\n\n\u003cbr\u003e\n\n![image](https://user-images.githubusercontent.com/15976103/95644909-a31bcd80-0aec-11eb-9270-869b0a94f59f.png)\n\n\u003c/details\u003e\n\n## 支持\n\n- **[Strava](#strava)**\n- **[New Way To Sync Nike Run Club](#nike-run-club-new)** ：NFC 同步的新方式\n- **[Nike Run Club](#nike-run-club)**\n- **[Garmin](#garmin)**\n- **[Garmin-cn](#garmin-cn-大陆用户请用这个)**\n- **[Keep](#keep)**\n- **[悦跑圈](#joyrun悦跑圈)** ：限制单个设备，无法自动化\n- **[咕咚](#codoon咕咚)** ：限制单个设备，无法自动化\n- **[郁金香运动](#tulipsport)**\n- **[GPX](#gpx)**\n- **[TCX](#tcx)**\n- **[FIT](#fit)**\n- **[佳明国内同步国际](#Garmin-CN-to-Garmin)**\n- **[Tcx+Strava(upload all tcx data to strava)](#tcx_to_strava)**\n- **[Tcx+Garmin(upload all tcx data to Garmin)](#tcx_to_garmin)**\n- **[Gpx+Strava(upload all gpx data to strava)](#gpx_to_strava)**\n- **[Nike+Strava(Using NRC Run, Strava backup data)](#nikestrava)**\n- **[Garmin_to_Strava(Using Garmin Run, Strava backup data)](#garmin_to_strava)**\n- **[Strava_to_Garmin(Using Strava Run, Garmin backup data)](#strava_to_garmin)**\n- **[Coros 高驰](#Coros高驰)**\n## 视频教程\n\n- https://www.youtube.com/watch?v=reLiY9p8EJk\n- https://www.youtube.com/watch?v=VdNkFxTX5QQ\n\n## 下载\n\n```bash\ngit clone https://github.com/yihong0618/running_page.git --depth=1\n```\n\n## 安装及测试 (node \u003e= 20 python \u003e= 3.11)\n\n```bash\npip3 install -r requirements.txt\nnpm install -g corepack \u0026\u0026 corepack enable \u0026\u0026 pnpm install\npnpm develop\n```\n\n访问 \u003chttp://localhost:5173/\u003e 查看\n\n## Docker\n\n```bash\n# NRC\ndocker build -t running_page:latest . --build-arg app=NRC --build-arg nike_refresh_token=\"\"\n\n# Garmin\ndocker build -t running_page:latest . --build-arg app=Garmin --build-arg secret_string=\"\"\n\n# Garmin-CN\ndocker build -t running_page:latest . --build-arg app=Garmin-CN --build-arg secret_string=\"\"\n\n# Strava\ndocker build -t running_page:latest . --build-arg app=Strava --build-arg client_id=\"\"  --build-arg client_secret=\"\"  --build-arg refresh_token=\"\"\n\n#Nike_to_Strava\ndocker build -t running_page:latest . --build-arg app=Nike_to_Strava  --build-arg nike_refresh_token=\"\" --build-arg client_id=\"\"  --build-arg client_secret=\"\"  --build-arg refresh_token=\"\"\n\n# Keep\ndocker build -t running_page:latest . --build-arg app=Keep --build-arg keep_phone_number=\"\" --build-arg keep_password=\"\"\n\n#启动\ndocker run -itd -p 80:80   running_page:latest\n\n#访问\n访问 ip:80 查看\n\n```\n\n## 替换 Mapbox token\n\n\u003e 建议有能力的同学把 `src/utils/const.ts` 文件中的 Mapbox token 自己的 [Mapbox token](https://www.mapbox.com/)\n\n\u003e 如果你是海外用户请更改 `IS_CHINESE = false` in `src/utils/const.ts`\n\n```typescript\nconst MAPBOX_TOKEN =\n  'pk.eyJ1IjoieWlob25nMDYxOCIsImEiOiJja2J3M28xbG4wYzl0MzJxZm0ya2Fua2p2In0.PNKfkeQwYuyGOTT_x9BJ4Q';\n```\n\n## 个性化设置\n\n\u003e 在仓库目录下找到 `src/static/site-metadata.ts`，找到以下内容并修改成你自己想要的。\n\n```typescript\nsiteMetadata: {\n  siteTitle: 'Running Page', #网站标题\n  siteUrl: 'https://yihong.run', #网站域名\n  logo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTtc69JxHNcmN1ETpMUX4dozAgAN6iPjWalQ\u0026usqp=CAU', #左上角 LOGO\n  description: 'Personal site and blog',\n  navLinks: [\n    {\n      name: 'Blog', #右上角导航名称\n      url: 'https://yihong.run/running', #右上角导航链接\n    },\n    {\n      name: 'About',\n      url: 'https://github.com/yihong0618/running_page/blob/master/README-CN.md',\n    },\n  ],\n},\n```\n\n\u003e 修改 `src/utils/const.ts` 文件中的样式：\n\n```typescript\n// styling: 关闭虚线：设置为 `false`\nconst USE_DASH_LINE = true;\n// styling: 透明度：[0, 1]\nconst LINE_OPACITY = 0.4;\n// update for now 2024/11/17 the privacy mode is true\n// styling: 开启隐私模式 (不显示地图仅显示轨迹): 设置为 `true`\n// 注意：此配置仅影响页面显示，数据保护请参考下方的 \"隐私保护\"\nconst PRIVACY_MODE = false;\n// styling: 默认关灯: 设置为 `false`, 仅在隐私模式关闭时生效(`PRIVACY_MODE` = false)\nconst LIGHTS_ON = true;\n// styling: 是否显示列 ELEVATION_GAIN\nconst SHOW_ELEVATION_GAIN = false;\nconst PRIVACY_MODE = true;\n// update for now 2024/11/17 the lights on default is false\n```\n\n\u003e 隐私保护：设置下面环境变量：\n\n```bash\n# 忽略每个 polyline 的起点和终点的长度（单位：米）。\nIGNORE_START_END_RANGE = 200\n\n# 忽略下面 polyline 中每个点的距离的圆圈（单位：米）。\nIGNORE_RANGE = 200\n\n# 包含要忽略的点的折线。\nIGNORE_POLYLINE = ktjrFoemeU~IorGq}DeB\n\n# 在保存到数据库之前进行过滤，你会丢失一些数据，但可以保护你的隐私，如果你使用的是公共仓库，建议设置为 1。不设置可关闭。\nIGNORE_BEFORE_SAVING = 1\n```\n\n\u003e 你可以使用`\nGoogle Maps` 的 [互动式多段线编码器实用程序](https://developers.google.com/maps/documentation/utilities/polylineutility)，来制作你的 `IGNORE_POLYLINE`。如果你在中国，请使用卫星图制作，避免火星坐标漂移。\n\n## 下载数据到本地\n\n\u003e 下载您的 Nike Run Club/Strava/Garmin/Garmin-cn/Keep 数据到本地，别忘了在 total 页面生成可视化 SVG\n\n### GPX\n\n\u003cdetails\u003e\n\u003csummary\u003eMake your \u003ccode\u003eGPX\u003c/code\u003e data\u003c/summary\u003e\n\n\u003cbr\u003e\n\n把其它软件生成的 `gpx files` 拷贝到 `GPX_OUT` 之后运行\n\n```bash\npython3(python) run_page/gpx_sync.py\n```\n\n\u003c/details\u003e\n\n### TCX\n\n\u003cdetails\u003e\n\u003csummary\u003eMake your \u003ccode\u003eTCX\u003c/code\u003e data\u003c/summary\u003e\n\n\u003cbr\u003e\n\n把其它软件生成的 `tcx files` 拷贝到 `TCX_OUT` 之后运行\n\n```bash\npython3(python) run_page/tcx_sync.py\n```\n\n\u003c/details\u003e\n\n### FIT\n\n\u003cdetails\u003e\n\u003csummary\u003eMake your \u003ccode\u003eFIT\u003c/code\u003e data\u003c/summary\u003e\n\n\u003cbr\u003e\n\n把其它软件生成的 fit files 拷贝到 FIT_OUT 之后运行\n\n```bash\npython3(python) run_page/fit_sync.py\n```\n\n\u003c/details\u003e\n\n### Keep\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Keep 数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n\u003e 确保自己的账号能用手机号 + 密码登陆 (不要忘记添加 secret 和更改自己的账号，在 GitHub Actions 中), 注：海外手机号需要换成国内 +86 的手机号\n\n```bash\npython3(python) run_page/keep_sync.py ${your mobile} ${your password}\n```\n\n示例：\n\n```bash\npython3(python) run_page/keep_sync.py 13333xxxx example\n```\n\n\u003e 我增加了 keep 可以导出 gpx 功能（因 keep 的原因，距离和速度会有一定缺失）, 执行如下命令，导出的 gpx 会加入到 GPX_OUT 中，方便上传到其它软件。\n\n```bash\npython3(python) run_page/keep_sync.py ${your mobile} ${your password} --with-gpx\n```\n\n示例：\n\n```bash\npython3(python) run_page/keep_sync.py 13333xxxx example --with-gpx \n```\n\n\u003e 增加了 keep 对其他运动类型的支持，目前可选的有 running, cycling, hiking，默认的运动数据类型为 running。\n\n```bash\npython3(python) run_page/keep_sync.py ${your mobile} ${your password} --with-gpx --sync-types running cycling hiking\n```\n\n示例：\n\n```bash\npython3(python) run_page/keep_sync.py 13333xxxx example --with-gpx --sync-types running cycling hiking\n```\n\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e路线偏移修正\u003c/summary\u003e\n\n\u003cbr\u003e\n\n如果您得到的运动路线与实际路线对比有整体偏移，可以修改代码中的参数进行修正\n\n\u003e Keep 目前采用的是 GCJ-02 坐标系，因此导致得到运动数据在使用 WGS-84 坐标系的平台（Mapbox、佳明等）中显示轨迹整体偏移\n\n- 修改 `run_page/keep_sync.py` 文件中的参数：\n\n```python\n# If your points need trans from gcj02 to wgs84 coordinate which use by Mappbox\nTRANS_GCJ02_TO_WGS84 = True\n```\n\n\u003c/details\u003e\n\n### JoyRun（悦跑圈）\n\n\u003e 因悦跑圈限制单个设备，无法自动化。\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的悦跑圈数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 获取登陆验证码：\n2. 确保自己的账号能用手机号 + 验证码登陆\n3. 点击获取验证码\n\n\u003e 不要在手机输入验证码，拿到验证码就好，用这个验证码放到下方命令中\n\n![image](https://user-images.githubusercontent.com/15976103/102352588-e3af3000-3fe2-11eb-8131-14946b0262eb.png)\n\n```bash\npython3(python) run_page/joyrun_sync.py ${your mobile} ${your 验证码} --athlete ${your own name}\n```\n\n示例：\n\n```bash\npython3(python) run_page/joyrun_sync.py 13333xxxx xxxx --athlete yihong0618\n```\n\njoyrun 导出 gpx 文件\n\n\u003e 导出的 gpx 在 GPX_OUT 目录，方便上传到其它软件\n\n```bash\npython3(python) run_page/joyrun_sync.py ${your mobile} ${your 验证码} --with-gpx\n```\n\n示例：\n\n```bash\npython3(python) run_page/joyrun_sync.py 13333xxxx example --with-gpx\n```\n\n\u003e 因为验证码有过期时间，我增加了 cookie uid sid 登陆的方式，uid 及 sid 在您登陆过程中会在控制台打印出来\n\n![image](https://user-images.githubusercontent.com/15976103/102354069-05a9b200-3fe5-11eb-9b30-221c32bbc607.png)\n\n示例：\n\n```bash\npython3(python) run_page/joyrun_sync.py 1393xx30xxxx 97e5fe4997d20f9b1007xxxxx --from-uid-sid --with-gpx\n```\n\n\u003e 支持配置 min_grid_distance，默认为 10\n\n```bash\npython3(python) run_page/joyrun_sync.py 13333xxxx xxxx --athlete yihong0618 --min_grid_distance 5 \n```\n\n\u003c/details\u003e\n\n### Codoon（咕咚）\n\n\u003e 因悦跑圈限制单个设备，无法自动化。\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的咕咚数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n```bash\npython3(python) run_page/codoon_sync.py ${your mobile or email} ${your password}\n```\n\n示例：\n\n```bash\npython3(python) run_page/codoon_sync.py 13333xxxx xxxx\n```\n\nCodoon 导出 gpx\n\n\u003e 导出的 gpx 在 GPX_OUT 目录，方便上传到其它软件\n\n```bash\npython3(python) run_page/codoon_sync.py ${your mobile or email} ${your password} --with-gpx\n```\n\n示例：\n\n```bash\npython3(python) run_page/codoon_sync.py 13333xxxx xxxx --with-gpx\n```\n\n\u003e 因为登录 token 有过期时间限制，我增加了 refresh_token\u0026user_id 登陆的方式，refresh_token 及 user_id 在您登陆过程中会在控制台打印出来\n\n![image](https://user-images.githubusercontent.com/6956444/105690972-9efaab00-5f37-11eb-905c-65a198ad2300.png)\n\n示例：\n\n```bash\npython3(python) run_page/codoon_sync.py 54bxxxxxxx fefxxxxx-xxxx-xxxx --from-auth-token\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e路线偏移修正\u003c/summary\u003e\n\n\u003cbr\u003e\n\n如果您得到的运动路线与实际路线对比有整体偏移，可以修改代码中的参数进行修正\n\n\u003e 咕咚最初采用 GCJ-02 坐标系，在 2014 年 3 月份左右升级为 WGS-84 坐标系，导致升级之前的运动数据在使用 WGS-84 坐标系的平台（Mapbox、佳明等）中显示轨迹整体偏移\n\n- 修改 `run_page/codoon_sync.py` 文件中的参数：\n\n\u003e TRANS_END_DATE 需要根据您的实际情况设定，程序会修正这一天之前的运动记录\n\n```python\n# If your points need trans from gcj02 to wgs84 coordinate which use by Mappbox\nTRANS_GCJ02_TO_WGS84 = True\n# trans the coordinate data until the TRANS_END_DATE, work with TRANS_GCJ02_TO_WGS84 = True\nTRANS_END_DATE = \"2014-03-24\"\n```\n\n\u003c/details\u003e\n\n### TulipSport\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的郁金香运动数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n\u003e 郁金香运动数据的获取方式采用开放平台授权模式，通过访问[RunningPage 授权页面](https://tulipsport.rdshoep.com)获取账号 TOKEN(不会过期，只能访问 2021 年之后的数据)，并在仓库的 GitHub Actions 环境配置中添加`TULIPSPORT_TOKEN`配置。\n\n```bash\npython3(python) run_page/tulipsport_sync.py ${tulipsport_token}\n```\n\n示例：\n\n```bash\npython3(python) run_page/tulipsport_sync.py nLgy****RyahI\n```\n\n\u003c/details\u003e\n\n### Garmin\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Garmin 数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- 如果你只想同步跑步数据增加命令 --only-run\n\n- 如果你想同步 `tcx` 格式，增加命令 --tcx\n\n- 如果你想同步 `fit` 格式，增加命令 --fit\n\n- 如果你使用 Garmin 作为数据源建议您将代码拉取到本地获取 Garmin 国际区的密钥，注意**Python 版本必须\u003e=3.8**\n\n#### 获取佳明国际区的密钥\n\n在终端中输入以下命令\n\n```bash\n# 获取密钥\npython3(python) run_page/get_garmin_secret.py ${your email} ${your password}\n```\n\n#### 执行佳明国际区同步脚本\n\n复制上述终端中输出的密钥，如果您是使用 Github 请在 Github Action 中配置**GARMIN_SECRET_STRING**参数\n\n示例：\n\n```bash\npython3(python) run_page/garmin_sync.py xxxxxxxxxxx\n```\n\n\u003c/details\u003e\n\n### Garmin-CN (大陆用户使用)\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Garmin CN 数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- 如果你只想同步跑步数据请增加 --only-run\n- 如果你想同步 `tcx` 格式，增加命令 --tcx\n- 如果你想同步 `fit` 格式，增加命令 --fit\n- 如果你使用 Garmin 作为数据源建议您将代码拉取到本地获取 Garmin 国际区的密钥，注意**Python 版本必须\u003e=3.10**\n\n#### 获取佳明 CN 的密钥\n\n在终端中输入以下命令\n\n```bash\n# to get secret_string\npython3(python) run_page/get_garmin_secret.py ${your email} ${your password} --is-cn\n```\n\n![get_garmin_cn_secret](docs/get_garmin_cn_secret.jpg)\n\n#### 执行佳明国区同步脚本\n\n复制上述终端中输出的密钥，如果您是使用 Github 请在 Github Action 中配置**GARMIN_SECRET_STRING_CN** 参数\n![get_garmin_secret](docs/add_garmin_secret_cn_string.jpg)\n示例：\n\n```bash\npython3(python) run_page/garmin_sync.py xxxxxxxxx --is-cn\n```\n\n仅同步跑步数据：\n\n```bash\npython3(python) run_page/garmin_sync.py xxxxxxxxxx --is-cn --only-run\n```\n\n\u003c/details\u003e\n\n### Garmin-CN to Garmin\n\n\u003cdetails\u003e\n\u003csummary\u003e 同步佳明 CN 数据到 佳明国际区\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- 如果你只想同步 `type running` 使用参数 --only-run\n**The Python version must be \u003e=3.10**\n\n#### 获取佳明 CN 的密钥\n\n在终端中输入以下命令\n\n```bash\npython3(python) run_page/get_garmin_secret.py ${your email} ${your password} --is-cn\n```\n\n#### 获取佳明全球的密钥\n\n在终端中输入以下命令\n\n```bash\npython3(python) run_page/get_garmin_secret.py ${your email} ${your password}\n```\n\n#### 同步 佳明 CN 到 佳明全球\n\n在终端中输入以下命令\n\n```bash\npython3(python) run_page/garmin_sync_cn_global.py ${garmin_cn_secret_string} ${garmin_secret_string}\n```\n\n\u003c/details\u003e\n\n### Nike Run Club New\n\n\u003cdetails\u003e\n\u003csummary\u003eGet your \u003ccode\u003eNike Run Club\u003c/code\u003e data\u003c/summary\u003e\n\n\u003cbr\u003e\n\n\u003e Please note:由于 nike run club 已经在中国大陆停止运营，所以只能通过 vpn 的方式进行登录。在开始之前先确认自己是全局的非中国大陆的代理，能够正确的访问`nike.com`而不是`nike.com.cn` 如下图所示。\n\n![nike.com](https://github.com/user-attachments/assets/8ce6ae8f-4bc6-4522-85ec-3e5b7590e96d)\n\u003cbr\u003e\n\n1. 登录/注册 [NikeRunClub](https://www.nike.com/) 账号\n   ![login](https://github.com/user-attachments/assets/659341fb-4abf-491e-bda7-bfca968921b3)\n2. 登录成功后，键盘打开 F12-\u003eApplication-\u003elocalstorage-\u003e 复制键为`https://www.nike.com`的值中的`access_token`的内容。\n   ![developer_mode](https://github.com/user-attachments/assets/c932318d-a123-4505-8fd8-b46946c25d29)\n3. 在根目录执行，你应该就可以看到下图中的内容，然后你就可以正常在你的手机版 NRC 里登录你的账号了：\n\n```bash\npython3(python) run_page/nike_sync.py ${access_token}\n```\n\n如果你同步了一次（已经完成同步）想继续同步新的\n```bash\npython3(python) run_page/nike_sync.py ${access_token} --continue-sync\n```\n\n![tg_image_166091873](https://github.com/user-attachments/assets/9d4851d6-849a-4bb7-8ffe-5358fa7328b2)\n\n如果你想自动化同步 NRC 中的运动数据，去 [issue692](https://github.com/yihong0618/running_page/issues/692#issuecomment-2218849713)中查看相关内容。\n\n\u003c/details\u003e\n\n### Nike Run Club\n\n\u003cdetails\u003e\n\u003csummary\u003e获取 Nike Run Club 数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n\u003e 请注意：当您选择将 running_page 部署在自己的服务器上时，由于 Nike 已经封禁了一部分 IDC 的服务器 IP 段，您的服务器可能不能正常同步 Nike Run Club 的数据并显示 `403 error` ，这时您将不得不选择其他的托管方式。\n\n获取 Nike 的 refresh_token\n\n**全部需要在大陆以外的全局 ip 下进行**\n\n![example img](https://user-images.githubusercontent.com/67903793/282300381-4e7437d0-65a9-4eed-93d1-2b70e360215f.png)\n\n1. 在这里登陆[website](https://unite.nike.com/s3/unite/mobile.html?androidSDKVersion=3.1.0\u0026corsoverride=https%3A%2F%2Funite.nike.com\u0026uxid=com.nike.sport.running.droid.3.8\u0026backendEnvironment=identity\u0026view=login\u0026clientId=VhAeafEGJ6G8e9DxRUz8iE50CZ9MiJMG), 打开 F12 在浏览器抓 login -\u003e XHR -\u003e get the `refresh_token` from login api\n\n2. 复制 `refresh_token` 之后可以添加在 GitHub Secrets 中，也可以直接在命令行中使用\n\n\u003e Chrome 浏览器：按下 F12 打开浏览器开发者工具，点击 Application 选项卡，来到左侧的 Storage 面板，点击展开 Local storage，点击下方的 https://unite.nike.com。接着点击右侧的 com.nike.commerce.nikedotcom.web.credential Key，下方会分行显示我们选中的对象，可以看到 refresh_token，复制 refresh_token 右侧的值。Safari 浏览器：在 Safari 打开 Nike 的网页后，右击页面，选择「检查元素」，打开浏览器开发者工具。点击「来源」选项卡，在左侧找到 XHR 文件夹，点击展开，在下方找到 login 文件并单击，在右侧同样可以看到 refresh_token，复制 refresh_token 右侧的值。\n\n```bash\npython3(python) run_page/nike_sync.py ${nike refresh_token}\n```\n\n示例：\n\n```bash\npython3(python) run_page/nike_sync.py eyJhbGciThiMTItNGIw******\n```\n\n![example img](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/nike_sync_%20example.png)\n\n\u003c/details\u003e\n\n### Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e获取 Strava 数据\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 注册/登陆 [Strava](https://www.strava.com/) 账号\n2. 登陆成功后打开 [Strava Developers](http://developers.strava.com) -\u003e [Create \u0026 Manage Your App](https://strava.com/settings/api)\n\n3. 创建 `My API Application`\n   输入下列信息：\n   ![My API Application](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/strava_settings_api.png)\n   创建成功：\n   ![](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/created_successfully_1.png)\n4. 使用以下链接请求所有权限\n   将 ${your_id} 替换为 My API Application 中的 Client ID 后访问完整链接\n\n```\nhttps://www.strava.com/oauth/authorize?client_id=${your_id}\u0026response_type=code\u0026redirect_uri=http://localhost/exchange_token\u0026approval_prompt=force\u0026scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write\n```\n\nExample:\n\n```\nhttps://www.strava.com/oauth/authorize?client_id=115321\u0026response_type=code\u0026redirect_uri=http://localhost/exchange_token\u0026approval_prompt=force\u0026scope=read_all,profile:read_all,activity:read_all,profile:write,activity:write\n```\n\n![get_all_permissions](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/get_all_permissions.png)\n\n5. 提取授权后返回链接中的 code 值\n   例如：\n\n```\nhttp://localhost/exchange_token?state=\u0026code=1dab37edd9970971fb502c9efdd087f4f3471e6e\u0026scope=read,activity:write,activity:read_all,profile:write,profile:read_all,read_all\n```\n\n`code` 数值为：\n\n```\n1dab37edd9970971fb502c9efdd087f4f3471e6\n```\n\n![get_code](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/get_code.png) 6. 使用 Client_id、Client_secret、Code 请求 refresh_token\n在 `终端/iTerm` 中执行：\n\n```bash\ncurl -X POST https://www.strava.com/oauth/token \\\n-F client_id=${Your Client ID} \\\n-F client_secret=${Your Client Secret} \\\n-F code=${Your Code} \\\n-F grant_type=authorization_code\n```\n\n示例：\n\n```bash\ncurl -X POST https://www.strava.com/oauth/token \\\n-F client_id=12345 \\\n-F client_secret=b21******d0bfb377998ed1ac3b0 \\\n-F code=d09******b58abface48003 \\\n-F grant_type=authorization_code\n```\n\n![get_refresh_token](https://raw.githubusercontent.com/shaonianche/gallery/master/running_page/get_refresh_token.png)\n\n7. 同步数据至 Strava\n   在项目根目录执行：\n\n\u003e 第一次同步 Strava 数据时需要更改在 strava_sync.py 中的第 12 行代码 False 改为 True，运行完成后，再改为 False。\n\n仅同步跑步数据，添加参数 --only-run\n\n```bash\npython3(python) run_page/strava_sync.py ${client_id} ${client_secret} ${refresh_token}\n```\n\n其他资料参见\n\u003chttps://developers.strava.com/docs/getting-started\u003e\n\u003chttps://github.com/barrald/strava-uploader\u003e\n\u003chttps://github.com/strava/go.strava\u003e\n\n\u003c/details\u003e\n\n### TCX_to_Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e上传所有的 tcx 格式的跑步数据到 strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 strava 的步骤\n2. 把 tcx 文件全部拷贝到 TCX_OUT 中\n3. 在项目根目录下执行：\n\n```bash\npython3(python) run_page/tcx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}\n```\n\n示例：\n\n```bash\npython3(python) run_page/tcx_to_strava_sync.py xxx xxx xxx\n或\npython3(python) run_page/tcx_to_strava_sync.py xxx xxx xxx --all\n```\n\n\u003e 如果你已经上传过需要跳过判断增加参数 `--all`\n\n\u003c/details\u003e\n\n### TCX_to_Garmin\n\n\u003cdetails\u003e\n\u003csummary\u003e上传所有的 tcx 格式的跑步数据到 Garmin\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 garmin 的步骤\n2. 把 tcx 文件全部拷贝到 TCX_OUT 中\n3. 在项目根目录下执行：\n\n```bash\npython3 run_page/tcx_to_garmin_sync.py ${{ secrets.GARMIN_SECRET_STRING_CN }} --is-cn\n```\n\n示例：\n\n```bash\npython run_page/tcx_to_garmin_sync.py xxx --is-cn\n或佳明国际\npython run_page/tcx_to_garmin_sync.py xxx\n```\n\n\u003e 如果你已经上传过需要跳过判断增加参数 `--all`\n\n\u003c/details\u003e\n\n### GPX_to_Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e上传所有的 gpx 格式的跑步数据到 strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 strava 的步骤\n2. 把 gpx 文件全部拷贝到 GPX_OUT 中\n3. 在项目根目录下执行：\n\n```bash\npython3(python) run_page/gpx_to_strava_sync.py ${client_id} ${client_secret} ${strava_refresh_token}\n```\n\n示例：\n\n```bash\npython3(python) run_page/gpx_to_strava_sync.py xxx xxx xxx\n或\npython3(python) run_page/gpx_to_strava_sync.py xxx xxx xxx --all\n```\n\n3. 如果你已经上传过需要跳过判断增加参数 `--all`\n\n\u003c/details\u003e\n\n### Nike+Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e获取 \u003ccode\u003eNike Run Club\u003c/code\u003e 的跑步数据然后同步到 Strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 nike 和 strava 的步骤\n2. 在项目根目录下执行：\n\n```bash\npython3(python) run_page/nike_to_strava_sync.py ${nike_refresh_token} ${client_id} ${client_secret} ${strava_refresh_token}\n```\n\n示例：\n\n```bash\npython3(python) run_page/nike_to_strava_sync.py eyJhbGciThiMTItNGIw******  xxx xxx xxx\n```\n\n\u003c/details\u003e\n\n### Garmin_to_Strava\n\n\u003cdetails\u003e\n\u003csummary\u003e获取你的\u003ccode\u003e佳明\u003c/code\u003e 的跑步数据，然后同步到 Strava\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 garmin 和 strava 的步骤\n2. 在项目根目录下执行：\n\n```bash\npython3(python) run_page/garmin_to_strava_sync.py  ${client_id} ${client_secret} ${strava_refresh_token} ${garmin_secret_string} --is-cn\n```\n\n示例：\n\n```bash\npython3(python) run_page/garmin_to_strava_sync.py  xxx xxx xxx xx xxx\n```\n\n\u003c/details\u003e\n\n### Strava_to_Garmin\n\n\u003cdetails\u003e\n\u003csummary\u003e获取你的\u003ccode\u003eStrava\u003c/code\u003e 的跑步数据然后同步到 Garmin\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 完成 garmin 和 strava 的步骤，同时，还需要在 Github Actions secret 那新增 Strava 配置：`secrets.STRAVA_EMAIL`、`secrets.STRAVA_PASSWORD`\n2. 在项目根目录下执行：\n\n```bash\npython3(python) run_page/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_SECRET_STRING }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }}\n```\n\n如果你的佳明账号是中国区，执行如下的命令：\n\n```bash\npython3(python) run_page/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_SECRET_STRING_CN }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --is-cn\n```\n\n如果要在同步到 Garmin 的运动记录中添加 Garmin 设备信息，需要添加`--use_fake_garmin_device`参数，这将在同步的 Garmin 锻炼记录中添加一个 Garmin 设备（默认情况下为 `Garmin Forerunner 245`，您可以在`garmin_device_adaptor.py`中更改设备信息），运动记录中有了设备信息之后就可以同步到其他 APP 中，比如数字心动（攒上马积分）这类不能通过 Apple Watch 同步的 APP，当然也可以同步到 Keep，悦跑圈，咕咚等 APP。\n\n\u003cimg width=\"830\" alt=\"image\" src=\"https://github.com/yihong0618/running_page/assets/8613196/b5076942-3133-4c89-ad66-a828211667dc\"\u003e\n\n最终执行的命令如下：\n\n```bash\npython3(python) run_page/strava_to_garmin_sync.py ${{ secrets.STRAVA_CLIENT_ID }} ${{ secrets.STRAVA_CLIENT_SECRET }} ${{ secrets.STRAVA_CLIENT_REFRESH_TOKEN }}  ${{ secrets.GARMIN_SECRET_STRING_CN }} ${{ secrets.STRAVA_EMAIL }} ${{ secrets.STRAVA_PASSWORD }} --use_fake_garmin_device\n```\n\n\u003e 注意：**首次初始化的时候，如果你有大量的 strava 跑步数据，可能有些数据会上传失败，只需要多重试几次即可。**\n\n\u003c/details\u003e\n\n### Coros 高驰\n\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Coros 高驰 数据\u003c/summary\u003e\n\n#### 在终端中输入以下命令\n\n```bash\npython run_page/coros_sync.py ${{ secrets.COROS_ACCOUNT }} ${{ secrets.COROS_PASSWORD }}\n```\n\n#### 修改 `run_data_sync.yml` 中 `env.RUN_TYPE: coros`\n\n#### 设置 github action 中 Coros 高驰信息\n\n- 在 github action 中配置 `COROS_ACCOUNT`,`COROS_PASSWORD` 参数\n\n  ![github-action](https://img3.uploadhouse.com/fileuploads/30980/3098042335f8995623f8b50776c4fad4cf7fff8d.png)\n\n\u003c/details\u003e\n\n### Keep_to_Strava\n\u003cdetails\u003e\n\u003csummary\u003e获取您的 Keep 数据，然后同步到 Strava\u003c/summary\u003e\n\n示例：\n```bash\npython3(python) run_page/keep_to_strava_sync.py ${your mobile} ${your password} ${client_id} ${client_secret} ${strava_refresh_token} --sync-types running cycling hiking\n```\n\n#### 解决的需求：\n1. 适用于由 Strava 总览/展示数据，但是有多种运动类型，且数据来自不同设备的用户。\n2. 适用于期望将华为运动健康/OPPO 健康等数据同步到 Strava 的用户 (前提是手机 APP 端已经开启了和 Keep 之间的数据同步)。\n3. 理论上华为/OPPO 等可以通过 APP 同步到 Keep 的设备，均可通过此方法自动同步到 Strava，目前已通过测试的 APP 有\n    - 华为运动健康：户外跑步，户外骑行，户外步行。\n\n#### 特性以及使用细节：\n1. 与 Keep 相似，但是由 keep_to_strava_sync.py 实现，不侵入 data.db 与 activities.json。因此不会出现由于同时使用 keep_sync 和 strava_sync 而导致的数据重复统计/展示问题。\n2. 上传至 Strava 时，会自动识别为 Strava 中相应的运动类型，目前支持的运动类型为 running, cycling, hiking。\n3. run_data_sync.yml 中的修改：\n\n    ```yaml\n    RUN_TYPE: keep_to_strava_sync\n    ```\n\n\u003c/details\u003e\n\n### Total Data Analysis\n\n\u003cdetails\u003e\n\u003csummary\u003e生成数据展示\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- 生成数据展示 SVG\n- 展示效果：[点击查看](https://raw.githubusercontent.com/yihong0618/running_page/master/assets/github.svg)、[点击查看](https://raw.githubusercontent.com/yihong0618/running_page/28fa801e4e30f30af5ae3dc906bf085daa137936/assets/grid.svg)\n\n\u003e 感兴趣的同学可以改下方参数 (--special-distance 10 --special-distance2 20, 10km~20km 展示为 special-color1 20km 以上展示为 special-color2, --min-distance 10.0 用来筛选 10km 以上的)\n\n```bash\npython3(python) run_page/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\n```\n\n```bash\npython3(python) run_page/gen_svg.py --from-db --title \"${{ env.TITLE_GRID }}\" --type grid --athlete \"${{ env.ATHLETE }}\"  --output assets/grid.svg --min-distance 10.0 --special-color yellow --special-color2 red --special-distance 20 --special-distance2 40 --use-localtime\n```\n\n生成年度环形数据\n\n```bash\npython3(python) run_page/gen_svg.py --from-db --type circular --use-localtime\n```\n\n更多展示效果参见：\n\u003chttps://github.com/flopp/GpxTrackPoster\u003e\n\n\u003c/details\u003e\n\n## server(recommend vercel)\n\n\u003cdetails\u003e\n\u003csummary\u003e使用 Vercel 部署\u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. vercel 连接你的 GitHub repo\n\n![image](https://user-images.githubusercontent.com/15976103/94452465-2599b880-01e2-11eb-9538-582f0f46c421.png)\n\n2. import repo\n\n![image](https://user-images.githubusercontent.com/15976103/94452556-3f3b0000-01e2-11eb-97a2-3789c2d60766.png)\n\n2. 等待部署完毕\n3. 访问\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e 使用 Cloudflare 部署 \u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 登录到 [Cloudflare 仪表板](https://dash.cloudflare.com)。\n\n2. 在左侧选择 `Workers 和 Pages`。\n\n3. 点击 `创建应用程序` 后选择 `Pages` 页面，链接您的 GitHub 账户并选择 `running_page` 仓库，点击 `开始设置`。\n\n4. 下滑到 `构建设置`，在 `框架预设` 中选择 `Create React App`，将 `构建输出目录` 设置为 `dist`。\n\n5. 下滑点击 `环境变量 (高级)`，并添加一个如下的变量：\n\n   \u003e 变量名称 = `PYTHON_VERSION`, 值 = `3.11`\n\n6. 点击 `保存并部署`，完成部署。\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e 部署到 GitHub Pages \u003c/summary\u003e\n\n\u003cbr\u003e\n\n1. 进入仓库的 \"Settings -\u003e GitHub Pages -\u003e Source\"，选择 \"GitHub Actions\"\n\n2. 进入仓库的 \"Actions -\u003e Workflows -\u003e All Workflows\"，选择左侧面板的 \"Run Data Sync\"，然后点击 \"Run workflow\"\n\n- \"Run Data Sync\" 将更新数据，然后触发 \"Publish GitHub Pages\" 工作流\n- 确认工作流运行没有错误\n\n3. 打开网站检查结果\n\n- 如果网站没有反映最新数据，请使用“F5”刷新页面\n- 某些浏览器 (比如 Chrome) 可能缓存网页不刷新，您需要使用 Ctrl+F5 (Windows) 或 Shift+Cmd+r (Mac) 强制清除缓存并重新加载页面\n\n4. 为 GitHub Actions 添加代码提交权限，访问仓库的 `Settings \u003e Actions \u003e General`页面，找到 `Workflow permissions` 的设置项，将选项配置为 `Read and write permissions`，支持 CI 将运动数据更新后提交到仓库中。\n\n\n5. 如果想把你的 running_page 部署在 xxx.github.io 而不是 xxx.github.io/run_page 亦或是想要添加自定义域名于 GitHub Pages，需要做三点\n\n-  修改你的 fork 的 running_page 仓库改名为 xxx.github.io, xxx 是你 github 的 username\n-  修改 gh-pages.yml 中的 Build 模块，删除 `${{ github.event.repository.name }}` 改为`run: PATH_PREFIX=/ pnpm build` 即可\n-  修改 src/static/site-metadata.ts 中 `siteUrl: ''` 或是添加你的自定义域名，`siteUrl: '[your_own_domain]'`，即可\n\n\u003c/details\u003e\n\n## GitHub Actions\n\n\u003e Fork 的同学请一定不要忘了把 GitHub Token 改成自己的，否则会 push 到我的 repo 中，谢谢大家。\n\n\u003cdetails\u003e\n\u003csummary\u003e修改 GitHub Actions Token\u003c/summary\u003e\n\n\u003cbr\u003e\n\nActions [源码](https://github.com/yihong0618/running_page/blob/master/.github/workflows/run_data_sync.yml)\n需要做如下步骤\n\n1. 更改成你的 app type 及 info\n   ![image](https://user-images.githubusercontent.com/15976103/94450124-73f98800-01df-11eb-9b3c-ac1a6224f46f.png)\n\n2. 在 `repo Settings` \u003e `Secrets` 中增加你的 secret (只添加你需要的即可)\n\n   ![image](https://user-images.githubusercontent.com/15976103/94450295-aacf9e00-01df-11eb-80b7-a92b9cd1461e.png)\n   我的 secret 如下\n   ![image](https://user-images.githubusercontent.com/15976103/94451037-8922e680-01e0-11eb-9bb9-729f0eadcdb7.png)\n\n\u003c/details\u003e\n\n## 快捷指令\n\n\u003cdetails\u003e\n\n\u003csummary\u003e使用 iOS 的 Shortcuts 实现自动化\u003c/summary\u003e\n\n\u003cbr\u003e\n\n下面拿 keep app 举例，当结束跑步后关闭 app，然后自动触发 Actions 更新数据。\n\n1. 拿到项目的 actions id（需要自行申请 token）\n\n```shell\ncurl https://api.github.com/repos/yihong0618/running_page/actions/workflows -H \"Authorization: token d8xxxxxxxxxx\" # change to your config\n```\n\n\u003ccenter\u003e\u003cimg src=\"https://cdn.jujimeizuo.cn/blog/2023/10/get-action-id.jpg\" alt=\"get-action-id\"\u003e\u003c/center\u003e\n\n2. 结合快捷指令\n\n   1. 通过 iCloud 获取 [running-page-shortcuts-template](https://www.icloud.com/shortcuts/4a5807a98b9a4e359815ff179c62bacb)\n\n   2. 修改下图字典参数\n   \u003ccenter\u003e \u003cimg src=\"https://cdn.jujimeizuo.cn/blog/2023/10/running-page-template.jpg\"\u003e \u003c/center\u003e\n\n3. 自动化\n\n\u003ccenter\u003e\n\u003cimg src=\"https://cdn.jujimeizuo.cn/blog/2023/10/new-automation.png\" width=20% height=20%\u003e\n\u003cimg src=\"https://cdn.jujimeizuo.cn/blog/2023/10/select-close.png\" width=20% height=20%\u003e\n\u003cimg src=\"https://cdn.jujimeizuo.cn/blog/2023/10/select-shortcut.png\" width=20% height=20%\u003e\n\u003cimg src=\"https://cdn.jujimeizuo.cn/blog/2023/10/finish-automation.png\" width=20% height=20%\u003e\n\u003c/center\u003e\n\n\u003c/details\u003e\n\n## Github Cache\n\n\u003cdetails\u003e\n\u003csummary\u003e把数据文件放在 GitHub Cache 中\u003c/summary\u003e\n\n\u003cbr\u003e\n\n`run_data_sync.yml` 中的 `SAVE_DATA_IN_GITHUB_CACHE` 设置为 `true` 时，可以把脚本抓取和中间产生的数据文件放到 GitHub Actions Cache 中。这样可以让你的 GitHub commit 历史和目录保持干净。\n\n如果你用 `GitHub Pages` 部署建议把这个值设置成 `true`。\n\n\u003c/details\u003e\n\n# Fit 文件\n\n测试发现，不同厂商在写 fit 文件的时候有略微差异。\n\n已调试设备：\n\n- [x] 佳明手表\n- [x] 迈金码表\n\n如果发现自己的 fit 文件解析有问题。可以提 issue。\n\n# TODO\n\n- [x] 完善这个文档\n- [x] 支持佳明，佳明中国\n- [x] 支持 keep\n- [ ] 支持苹果自带运动\n- [x] 支持 nike + strava\n- [x] 支持咕咚\n- [ ] 尝试支持小米运动\n- [x] 支持英语\n- [x] 完善代码\n- [x] 清理整个项目\n- [x] 完善前端代码\n- [x] better actions\n- [ ] tests\n- [x] 支持不同的运动类型\n\n# 参与项目\n\n- 任何 Issues PR 均欢迎。\n- 可以提交 PR share 自己的 Running page 在 README 中。\n- 提交 PR 前，使用 black 对 Python 代码进行格式化。(`black .`)\n\n# 特别感谢\n\n- @[flopp](https://github.com/flopp) 特别棒的项目 [GpxTrackPoster](https://github.com/flopp/GpxTrackPoster)\n- @[danpalmer](https://github.com/danpalmer) 原始的 UI 设计\n- @[shaonianche](https://github.com/shaonianche) icon 设计及文档\n- @[geekplux](https://github.com/geekplux) 帮助及鼓励，重构了前端代码，学到了不少\n- @[ben-29](https://github.com/ben-29) 搞定了咕咚，和我一起搞定了悦跑圈，太厉害了\n- @[MFYDev](https://github.com/MFYDev) Wiki\n\n# 推荐的 Forks\n\n- @[gongzili456](https://github.com/gongzili456) for [摩托车骑行版本](https://github.com/gongzili456/running_page)\n- @[ben-29](https://github.com/ben-29) for [多种运动类型支持](https://github.com/ben-29/workouts_page)\n- @[geekplux](https://github.com/geekplux) for [多种运动类型支持](https://github.com/geekplux/activities)\n\n# 赞赏\n\n谢谢就够了\n\n# Raycast 插件\n\n\u003ca title=\"Install running-page Raycast Extension\" href=\"https://www.raycast.com/Lemon/running-page\"\u003e\u003cimg src=\"https://www.raycast.com/Lemon/running-page/install_button@2x.png?v=1.1\" height=\"64\" alt=\"\" style=\"height: 64px;\"\u003e\u003c/a\u003e\n\n# FAQ\n\n- Strava 100 每 15 分钟的请求，1000 每日限制\n\n  \u003chttps://www.strava.com/settings/api\u003e\n  \u003chttps://developers.strava.com/docs/#rate-limiting\u003e\n\n  等待时间限制（这里是 strava 接口请求限制），不要关闭终端，这里会自动执行下一组上传数据\n\n  ```\n  Strava API Rate Limit Exceeded. Retry after 100 seconds\n  Strava API Rate Limit Timeout. Retry in 799.491622 seconds\n  ```\n\n- vercel git\n\n  如果想 ignore gh-pages 可以在 `settings` -\u003e `build` -\u003e `Ignored Build Step` -\u003e `Custom` 输入命令：\n\n  ```bash\n  if [ \"$VERCEL_GIT_COMMIT_REF\" != \"gh-pages\" ]; then exit 1; else exit 0;\n  ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyihong0618%2Frunning_page","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyihong0618%2Frunning_page","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyihong0618%2Frunning_page/lists"}