garmsync garmsync
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.3 KiB

5 months ago
5 months ago
5 months ago
5 months ago
  1. import gc from 'garmin-connect';
  2. import Trimlog from './lib/client.mjs';
  3. import { generateTrimlogInput, today } from './lib/tcx.mjs';
  4. async function main() {
  5. const garmin = new gc.GarminConnect({
  6. username: process.env.GARMIN_USERNAME,
  7. password: process.env.GARMIN_PASSWORD,
  8. });
  9. const trimlog = new Trimlog({
  10. username: process.env.TRIMLOG_USERNAME,
  11. password: process.env.TRIMLOG_PASSWORD,
  12. })
  13. await trimlog.refreshToken();
  14. await garmin.login();
  15. const blackList = {};
  16. setInterval(async() => {
  17. const looseActivities = await trimlog.getLooseActivities();
  18. const recentWorkouts = await trimlog.getWorkouts();
  19. const activities = await garmin.getActivities();
  20. const todayDate = today();
  21. for (const act of activities) {
  22. const id = Math.round(act.activityId).toFixed(0);
  23. if (blackList[id]) {
  24. continue;
  25. }
  26. if (!["walking", "cycling"].includes(act.activityType?.typeKey)) {
  27. console.error("Skipping", act.activityId, `(${act.activityType?.typeKey} activity not supported)`);
  28. blackList[id] = true;
  29. continue;
  30. }
  31. if (!act.startTimeLocal.startsWith(todayDate)) {
  32. console.error("Skipping", act.activityId, "(not today)");
  33. blackList[id] = true;
  34. continue;
  35. }
  36. if (looseActivities.find(l => l.tags.find(t => t.key === "gc:ActivityID" && t.value === id))) {
  37. console.error("Skipping", act.activityId, "(loose activity exists)");
  38. blackList[id] = true;
  39. continue;
  40. }
  41. if (recentWorkouts.find(l => l.tags.find(t => t.key === "gc:ActivityID" && t.value === id))) {
  42. console.error("Skipping", act.activityId, "(workout exists)");
  43. blackList[id] = true;
  44. continue;
  45. }
  46. console.log("Going ahead with", act.activityId, act.activityType.typeKey)
  47. await garmin.downloadOriginalActivityData(act, "/tmp/", "tcx")
  48. const input = await generateTrimlogInput(`/tmp/${act.activityId}.tcx`, act.activityName, act.activityType?.typeKey)
  49. input.tags.push({key: "gc:ActivityID", value: id})
  50. await trimlog.postWorkout(input);
  51. blackList[id] = true;
  52. }
  53. }, 300000);
  54. process.on('SIGINT', function() {
  55. console.log("INTERRUPTED");
  56. process.exit(0);
  57. });
  58. process.on('SIGTERM', function() {
  59. console.log("TERMINATED");
  60. process.exit(0);
  61. });
  62. }
  63. main();