Guest User

gc-export-steps

a guest
Apr 14th, 2021
937
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* v1 (2021-04-14) */
  2. function gcExportDailySteps() {
  3.     let loc = window.location.href
  4.  
  5.     let connectURL = "https://connect.garmin.com";
  6.     let dailyURL = "https://connect.garmin.com/modern/daily-summary/"
  7.     if (loc.indexOf(connectURL) != 0 || typeof jQuery === "undefined") {
  8.         alert(
  9. `You must be logged into Garmin Connect to run this script: : ${connectURL}`
  10. );
  11.         return;
  12.     }
  13.  
  14.     // Garmin Connect uses jQuery, so it's available for this script
  15.     jQuery("#_gc-steps_modal").remove();
  16.  
  17.     let xhr = new XMLHttpRequest();
  18.     xhr.open('GET', 'https://connect.garmin.com/modern/currentuser-service/user/info');
  19.     xhr.setRequestHeader("NK", "NT")
  20.     xhr.onload = function () {
  21.         let obj = JSON.parse(xhr.response)
  22.         _gcExportDailySteps(obj.displayName);
  23.     };
  24.     xhr.send()
  25.  
  26.     function _gcExportDailySteps(username) {
  27.         let today = new Date();
  28.  
  29.         if (loc.indexOf(dailyURL) == 0) {
  30.             let todayStr = loc.replace(dailyURL, "");
  31.             const dateRegExp = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
  32.             const match = todayStr.match(dateRegExp);
  33.             if (match && match.length !== 0) {
  34.                 today = new Date(match[1], match[2]-1, match[3]);
  35.             }
  36.         }
  37.  
  38.         let defaultStartDate = formatDate(incrementDate(today, -6));
  39.         let startDate = promptDate(
  40.     `Garmin Steps"
  41.  
  42.    Get daily steps for date starting:
  43.    `,
  44.            defaultStartDate
  45.        )
  46.  
  47.        if (!startDate) {
  48.            return;
  49.        }
  50.  
  51.        let defaultEndDate = formatDate(today, -6);
  52.        let endDate = promptDate(
  53.    `Garmin Steps"
  54.  
  55.     Get daily steps for date ending:
  56.     `,
  57.             defaultEndDate
  58.         )
  59.  
  60.         if (!endDate) {
  61.             return;
  62.         }
  63.  
  64.         startDate = formatDate(startDate);
  65.         endDate = formatDate(endDate);
  66.  
  67.         let xhr = new XMLHttpRequest();
  68.         xhr.open('GET', `https://connect.garmin.com/modern/proxy/userstats-service/wellness/daily/${username}?fromDate=${startDate}&untilDate=${endDate}&metricId=29&metricId=38&grpParentActType=false`);
  69.         xhr.setRequestHeader("NK", "NT")
  70.         xhr.onload = function () {
  71.             let obj = JSON.parse(xhr.response)
  72.             addDialog(obj, startDate, endDate)
  73.         };
  74.         xhr.send()
  75.     }
  76.  
  77.  
  78.     function incrementDate(date, amount) {
  79.         var tmpDate = new Date(date);
  80.         tmpDate.setDate(tmpDate.getDate() + amount)
  81.         return tmpDate;
  82.     }
  83.  
  84.     function formatDate(date) {
  85.         let d = new Date(date),
  86.             month = '' + (d.getMonth() + 1),
  87.             day = '' + d.getDate(),
  88.             year = d.getFullYear();
  89.    
  90.         if (month.length < 2)
  91.             month = '0' + month;
  92.         if (day.length < 2)
  93.             day = '0' + day;
  94.    
  95.         return [year, month, day].join('-');
  96.     }
  97.  
  98.     function promptDate(str, def) {
  99.         while (true) {
  100.             const val = prompt(str, def);
  101.             if (!val) {
  102.                 return val;
  103.             }
  104.  
  105.             const dateRegExp = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
  106.             const match = val.match(dateRegExp);
  107.             if (!match || match.length == 0) {
  108.                 continue;
  109.             }
  110.             let d;
  111.             d = new Date(match[1], match[2]-1, match[3], 0, 0, 0);
  112.             // console.log(d)
  113.             return d;
  114.         }
  115.     }
  116.  
  117.     function getCSV(data) {
  118.         const metricsMap = data.allMetrics.metricsMap;
  119.         const days = [
  120.             "Sunday",
  121.             "Monday",
  122.             "Tuesday",
  123.             "Wednesday",
  124.             "Thursday",
  125.             "Friday",
  126.             "Saturday",
  127.         ]
  128.         let csv =
  129. `Date,Day of Week,Actual Steps,Goal Steps\n`;
  130.         for (let i = 0; i < metricsMap.WELLNESS_TOTAL_STEPS.length; i++) {
  131.             const date = metricsMap.WELLNESS_TOTAL_STEPS[i].calendarDate;
  132.  
  133.             const dateRegExp = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
  134.             const match = date.match(dateRegExp);
  135.             let day = "";
  136.             if (match && match.length > 3) {
  137.                 let d;
  138.                 d = new Date(match[1], match[2]-1, match[3], 0, 0, 0);
  139.                 let dayNum = d.getDay();
  140.                 day = days[dayNum];
  141.             }
  142.  
  143.             csv +=
  144. `${date},${day},${metricsMap.WELLNESS_TOTAL_STEPS[i].value},${metricsMap.WELLNESS_TOTAL_STEP_GOAL[i].value}\n`;
  145.         }
  146.         return csv;
  147.     }
  148.  
  149.     function addDialog(data, startDate, endDate) {
  150.         addCSS();
  151.         jQuery("#_gc-steps_modal").remove();
  152.  
  153.         const output = JSON.stringify(data, null, 2)
  154.         const csv = getCSV(data);
  155.         jQuery('body').append(`
  156.             <div id="_gc-steps_modal" class="_gc-steps-modalDialog">
  157.                 <div><a href="#" title="Close" id="_gc-steps-close" class="_gc-steps-close">X</a>
  158.    
  159.                         <h2>Garmin Steps: ${startDate} to ${endDate}</h2>
  160.                     CSV:
  161.                     <textarea readonly id="_gc-steps-csv_textarea" rows="4" style="width:100%" spellcheck="false"
  162.                     >${csv}</textarea>
  163.                     <br>
  164.                     <br>
  165.                     <div>
  166.                         <div style="float:left">
  167.                             <button class="_gc-steps-btn" id="_gc-steps-csv_copy">Copy CSV to Clipboard</button>
  168.                             <span id="_gc-steps-csv-copied" style="display:none">CSV data copied to clipboard 👍</span>
  169.                         </div>
  170.                         <div style="float:right">
  171.                             <a class="_gc-steps-btn" download='steps-export.csv' href='data:text/plain;charset=utf-8,${escape(csv)}'>Download CSV</a>
  172.                         </div>
  173.                         <div style="clear:both"></div>
  174.                         <hr>
  175.                         JSON:
  176.                         <textarea readonly id="_gc-steps_textarea" rows="4" style="width:100%" spellcheck="false"
  177.                         >${output}</textarea>
  178.                         <br>
  179.                         <br>
  180.                         <div>
  181.                             <div style="float:left">
  182.                                 <button class="_gc-steps-btn" id="_gc-steps_copy">Copy JSON to Clipboard</button>
  183.                                 <span id="_gc-steps-copied" style="display:none">JSON data copied to clipboard 👍</span>
  184.                             </div>
  185.                             <div style="float:right">
  186.                                 <a class="_gc-steps-btn" download='steps-export.txt' href='data:text/plain;charset=utf-8,${escape(output)}'>Download JSON</a>
  187.                             </div>
  188.                         </div>
  189.                         <div style="clear:both"></div>
  190.                     </div>
  191.                 </div>
  192.             </div>
  193.     `);
  194.         jQuery("#_gc-steps-close").click(function() {
  195.             jQuery("#_gc-steps_modal").remove();
  196.             return false;
  197.         });
  198.         jQuery("#_gc-steps_copy").click(function() {
  199.             let el = document.getElementById("_gc-steps_textarea");
  200.             el.select();
  201.             document.execCommand('copy');
  202.             jQuery("#_gc-steps-copied").show();
  203.             return false;
  204.         });
  205.         jQuery("#_gc-steps-csv_copy").click(function() {
  206.             let el = document.getElementById("_gc-steps-csv_textarea");
  207.             el.select();
  208.             document.execCommand('copy');
  209.             jQuery("#_gc-steps-csv-copied").show();
  210.             return false;
  211.         });
  212.     }
  213.  
  214.     function addCSS() {
  215.         // based on https://jsfiddle.net/kumarmuthaliar/GG9Sa/1/
  216.         let styles = `
  217.     ._gc-steps-modalDialog {
  218.         position: fixed;
  219.         font-family: Arial, Helvetica, sans-serif;
  220.         top: 0;
  221.         right: 0;
  222.         bottom: 0;
  223.         left: 0;
  224.         background: rgba(0, 0, 0, 0.8);
  225.         z-index: 99999;
  226.         // opacity:0;
  227.         -webkit-transition: opacity 400ms ease-in;
  228.         -moz-transition: opacity 400ms ease-in;
  229.         transition: opacity 400ms ease-in;
  230.     }
  231.    
  232.     ._gc-steps-modalDialog > div {
  233.         width: 600px;
  234.         position: relative;
  235.         margin: 20px auto;
  236.         padding: 5px 20px 13px 20px;
  237.         border-radius: 10px;
  238.         background: #eee;
  239.         /*background: -moz-linear-gradient(#fff, #999);
  240.         background: -webkit-linear-gradient(#fff, #999);
  241.         background: -o-linear-gradient(#fff, #999);*/
  242.     }
  243.     ._gc-steps-close {
  244.         background: #606061;
  245.         color: #FFFFFF;
  246.         line-height: 25px;
  247.         position: absolute;
  248.         right: -12px;
  249.         text-align: center;
  250.         top: -10px;
  251.         width: 24px;
  252.         text-decoration: none;
  253.         font-weight: bold;
  254.         -webkit-border-radius: 12px;
  255.         -moz-border-radius: 12px;
  256.         border-radius: 12px;
  257.         -moz-box-shadow: 1px 1px 3px #000;
  258.         -webkit-box-shadow: 1px 1px 3px #000;
  259.         box-shadow: 1px 1px 3px #000;
  260.     }
  261.     ._gc-steps-close:hover {
  262.         background: #00d9ff;
  263.     }
  264.    
  265.     ._gc-steps-btn, ._gc-steps-btn:hover, ._gc-steps-btn:visited, ._gc-steps-btn:active {
  266.         color: #fff;
  267.         background-color: #337ab7;
  268.         border-color: #2e6da4;
  269.         text-decoration:none;
  270.    
  271.         display: inline-block;
  272.         margin-bottom: 0;
  273.         font-weight: 400;
  274.         text-align: center;
  275.         white-space: nowrap;
  276.         vertical-align: middle;
  277.         -ms-touch-action: manipulation;
  278.         touch-action: manipulation;
  279.         cursor: pointer;
  280.         background-image: none;
  281.         border: 1px solid transparent;
  282.         border-top-color: transparent;
  283.         border-right-color: transparent;
  284.         border-bottom-color: transparent;
  285.         border-left-color: transparent;
  286.         padding: 6px 12px;
  287.         font-size: 14px;
  288.         line-height: 1.42857143;
  289.         border-radius: 4px;
  290.     }
  291.  
  292.     #_gc-steps_textarea,
  293.     #_gc-steps-csv_textarea {
  294.         font-family: "Lucida Console", Monaco, Monospace
  295.     }
  296.     `
  297.    
  298.         jQuery("#_gc-steps_styles").remove();
  299.         let styleSheet = document.createElement("style")
  300.         styleSheet.type = "text/css"
  301.         styleSheet.id = "_gc-steps_styles"
  302.         styleSheet.innerText = styles
  303.         document.head.appendChild(styleSheet);
  304.    
  305.     }    
  306. }
  307.  
  308. gcExportDailySteps();
Advertisement
Add Comment
Please, Sign In to add comment