import re
regex = re.compile(r"^(/\*)(\n)(\*)(.*?)(\n)(\*/$)|(?<!:)(//)(.*?)$", flags=re.MULTILINE)
test_str = ("// intraday.gs -- Supports downloading intraday (minute-by-minute) step data\n"
"// Will not work without special permission from Fitbit\n\n"
"// Simon Bromberg (http://sbromberg.com)\n"
"// You are free to use, modify, copy any of the code in this script for your own purposes, as long as it's not for evil\n"
"// If you do anything cool with it, let me know!\n"
"// Note: there are minor improvements/cleanups still to be made in this file, but it should work as is if everything is setup properly\n"
"// See readme on github repo for more information\n\n"
"// Script based on post here http://quantifiedself.com/2014/09/download-minute-fitbit-data/ by Ernesto Ramirez\n"
"/*\n"
"* Do not change these key names. These are just keys to access these properties once you set them up by running the Setup function from the Fitbit menu\n"
"*/\n"
"// Key of ScriptProperty for Firtbit consumer key.\n"
"var CONSUMER_KEY_PROPERTY_NAME = \"fitbitConsumerKey\";\n"
"// Key of ScriptProperty for Fitbit consumer secret.\n"
"var CONSUMER_SECRET_PROPERTY_NAME = \"fitbitConsumerSecret\";\n\n"
"var SERVICE_IDENTIFIER = 'fitbit';\n\n"
"function onOpen() {\n"
" var ss = SpreadsheetApp.getActiveSpreadsheet();\n"
" var menuEntries = [\n"
" {\n"
" name: \"Setup\",\n"
" functionName: \"setup\"\n"
" },\n"
" {\n"
" name: \"Authorize\",\n"
" functionName: \"showSidebar\"\n"
" },\n"
" {\n"
" name: \"Reset\",\n"
" functionName: \"clearService\"\n"
" },\n"
" {\n"
" name: \"Download data\",\n"
" functionName: \"refreshTimeSeries\"\n"
" }];\n"
" ss.addMenu(\"Fitbit\", menuEntries);\n"
"}\n\n\n"
"function isConfigured() {\n"
" return getConsumerKey() != \"\" && getConsumerSecret() != \"\";\n"
"}\n\n"
"function setConsumerKey(key) {\n"
" ScriptProperties.setProperty(CONSUMER_KEY_PROPERTY_NAME, key);\n"
"}\n\n"
"function getConsumerKey() {\n"
" var key = ScriptProperties.getProperty(CONSUMER_KEY_PROPERTY_NAME);\n"
" if (key == null) {\n"
" key = \"\";\n"
" }\n"
" return key;\n"
"}\n\n"
"function setLoggables(loggable) {\n"
" ScriptProperties.setProperty(\"loggables\", loggable);\n"
"}\n\n"
"function getLoggables() {\n"
" var loggable = ScriptProperties.getProperty(\"loggables\");\n"
" if (loggable == null) {\n"
" loggable = LOGGABLES;\n"
" } else {\n"
" loggable = loggable.split(',');\n"
" }\n"
" return loggable;\n"
"}\n\n"
"function setConsumerSecret(secret) {\n"
" ScriptProperties.setProperty(CONSUMER_SECRET_PROPERTY_NAME, secret);\n"
"}\n\n"
"function getConsumerSecret() {\n"
" var secret = ScriptProperties.getProperty(CONSUMER_SECRET_PROPERTY_NAME);\n"
" if (secret == null) {\n"
" secret = \"\";\n"
" }\n"
" return secret;\n"
"}\n\n"
"// function saveSetup saves the setup params from the UI\n"
"function saveSetup(e) {\n"
" setConsumerKey(e.parameter.consumerKey);\n"
" setConsumerSecret(e.parameter.consumerSecret);\n"
" setLoggables(e.parameter.loggables);\n"
" setFirstDate(e.parameter.firstDate);\n"
" setLastDate(e.parameter.lastDate);\n"
" var app = UiApp.getActiveApplication();\n"
" app.close();\n"
" return app;\n"
"}\n\n"
"function setFirstDate(firstDate) {\n"
" ScriptProperties.setProperty(\"firstDate\", firstDate);\n"
"}\n\n"
"function getFirstDate() {\n"
" var firstDate = ScriptProperties.getProperty(\"firstDate\");\n"
" if (firstDate == null) {\n"
" firstDate = \"2012-01-01\";\n"
" }\n"
" return firstDate;\n"
"}\n\n"
"function setLastDate(lastDate) {\n"
" ScriptProperties.setProperty(\"lastDate\", lastDate);\n"
"}\n\n"
"function getLastDate() {\n"
" var lastDate = ScriptProperties.getProperty(\"lastDate\");\n"
" if (lastDate == null) {\n"
" var today = new Date();\n"
" lastDate = Utilities.formatDate(new Date(), SpreadsheetApp.getActive().getSpreadsheetTimeZone(),\"yyyy-mm-dd\");\n"
" }\n"
" return lastDate;\n"
"}\n\n"
"// function setup accepts and stores the Consumer Key, Consumer Secret, Project Key, firstDate, and list of Data Elements\n"
"function setup() {\n"
" var doc = SpreadsheetApp.getActiveSpreadsheet();\n"
" var app = UiApp.createApplication().setTitle(\"Setup Fitbit Download\");\n"
" app.setStyleAttribute(\"padding\", \"10px\");\n\n"
" var consumerKeyLabel = app.createLabel(\"Fitbit OAuth 2.0 Client ID:*\");\n"
" var consumerKey = app.createTextBox();\n"
" consumerKey.setName(\"consumerKey\");\n"
" consumerKey.setWidth(\"100%\");\n"
" consumerKey.setText(getConsumerKey());\n"
" \n"
" var consumerSecretLabel = app.createLabel(\"Fitbit OAuth Consumer Secret:*\");\n"
" var consumerSecret = app.createTextBox();\n"
" consumerSecret.setName(\"consumerSecret\");\n"
" consumerSecret.setWidth(\"100%\");\n"
" consumerSecret.setText(getConsumerSecret());\n"
" \n"
" var projectKeyTitleLabel = app.createLabel(\"Project key: \");\n"
" var projectKeyLabel = app.createLabel(ScriptApp.getProjectKey());\n"
" \n"
" var firstDate = app.createTextBox().setId(\"firstDate\").setName(\"firstDate\");\n"
" firstDate.setName(\"firstDate\");\n"
" firstDate.setWidth(\"100%\");\n"
" firstDate.setText(getFirstDate());\n\n"
" var lastDate = app.createTextBox().setId(\"lastDate\").setName(\"lastDate\");\n"
" lastDate.setName(\"lastDate\");\n"
" lastDate.setWidth(\"100%\");\n"
" lastDate.setText(getLastDate());\n"
" // create the save handler and button\n"
" var saveHandler = app.createServerClickHandler(\"saveSetup\");\n"
" var saveButton = app.createButton(\"Save Setup\", saveHandler);\n\n"
" // put the controls in a grid\n"
" var listPanel = app.createGrid(8, 3);\n"
" listPanel.setWidget(1, 0, consumerKeyLabel);\n"
" listPanel.setWidget(1, 1, consumerKey);\n"
" listPanel.setWidget(2, 0, consumerSecretLabel);\n"
" listPanel.setWidget(2, 1, consumerSecret);\n"
" listPanel.setWidget(3, 0, app.createLabel(\" * (obtain these at dev.fitbit.com, use OAuth2.0)\"));\n"
" listPanel.setWidget(4, 0, projectKeyTitleLabel);\n"
" listPanel.setWidget(4, 1, projectKeyLabel);\n"
" listPanel.setWidget(5, 0, app.createLabel(\"Start Date for download (yyyy-mm-dd)\"));\n"
" listPanel.setWidget(5, 1, firstDate);\n"
" listPanel.setWidget(6, 0, app.createLabel(\"End date for download (yyyy-mm-dd)\"));\n"
" listPanel.setWidget(6, 1, lastDate);\n"
" listPanel.setWidget(7, 0, app.createLabel(\"Very long intervals will not work; exceed Fitbit rate limit and/or function will timeout\"));\n"
" \n"
" // Ensure that all controls in the grid are handled\n"
" saveHandler.addCallbackElement(listPanel);\n"
" // Build a FlowPanel, adding the grid and the save button\n"
" var dialogPanel = app.createFlowPanel();\n"
" dialogPanel.add(listPanel);\n"
" dialogPanel.add(saveButton);\n"
" app.add(dialogPanel);\n"
" doc.show(app);\n"
"}\n\n"
"function getFitbitService() {\n"
" // Create a new service with the given name. The name will be used when\n"
" // persisting the authorized token, so ensure it is unique within the\n"
" // scope of the property store\n"
" Logger.log(PropertiesService.getUserProperties());\n"
" return OAuth2.createService(SERVICE_IDENTIFIER)\n\n"
" // Set the endpoint URLs, which are the same for all Google services.\n"
" .setAuthorizationBaseUrl('https://www.fitbit.com/oauth2/authorize')\n"
" .setTokenUrl('https://api.fitbit.com/oauth2/token')\n\n"
" // Set the client ID and secret, from the Google Developers Console.\n"
" .setClientId(getConsumerKey())\n"
" .setClientSecret(getConsumerSecret())\n\n"
" // Set the name of the callback function in the script referenced\n"
" // above that should be invoked to complete the OAuth flow.\n"
" .setCallbackFunction('authCallback')\n\n"
" // Set the property store where authorized tokens should be persisted.\n"
" .setPropertyStore(PropertiesService.getUserProperties())\n\n"
" .setScope('activity profile')\n"
" \n"
" .setTokenHeaders({\n"
" 'Authorization': 'Basic ' + Utilities.base64Encode(getConsumerKey() + ':' + getConsumerSecret())\n"
" });\n\n"
"}\n\n"
"function clearService(){\n"
" OAuth2.createService(SERVICE_IDENTIFIER)\n"
" .setPropertyStore(PropertiesService.getUserProperties())\n"
" .reset();\n"
"}\n\n"
"function showSidebar() {\n"
" var service = getFitbitService();\n"
" if (!service.hasAccess()) {\n"
" var authorizationUrl = service.getAuthorizationUrl();\n"
" var template = HtmlService.createTemplate(\n"
" '<a href=\"<?= authorizationUrl ?>\" target=\"_blank\">Authorize</a>. ' +\n"
" 'Reopen the sidebar when the authorization is complete.');\n"
" template.authorizationUrl = authorizationUrl;\n"
" var page = template.evaluate();\n"
" SpreadsheetApp.getUi().showSidebar(page);\n"
" } else {\n"
" Logger.log(\"Has access!!!!\");\n"
" }\n"
"}\n\n"
"function authCallback(request) {\n"
" Logger.log(\"authcallback\");\n"
" var service = getFitbitService();\n"
" var isAuthorized = service.handleCallback(request);\n"
" if (isAuthorized) {\n"
" Logger.log(\"success\");\n"
" return HtmlService.createHtmlOutput('Success! You can close this tab.');\n"
" } else {\n"
" Logger.log(\"denied\");\n"
" return HtmlService.createHtmlOutput('Denied. You can close this tab');\n"
" }\n"
"}\n\n"
"function getUser() {\n"
" var service = getFitbitService();\n\n"
" var options = {\n"
" headers: {\n"
" \"Authorization\": \"Bearer \" + service.getAccessToken(),\n"
" \"method\": \"GET\"\n"
" }};\n"
" var response = UrlFetchApp.fetch(\"https://api.fitbit.com/1/user/-/profile.json\",options);\n"
" var o = JSON.parse(response.getContentText());\n"
" return o.user;\n"
"}\n\n"
"function refreshTimeSeries() {\n"
" if (!isConfigured()) {\n"
" setup();\n"
" return;\n"
" }\n"
" var user = getUser();\n"
" var doc = SpreadsheetApp.getActiveSpreadsheet();\n"
" doc.setFrozenRows(2);\n"
" // two header rows\n"
" doc.getRange(\"a1\").setValue(user.fullName);\n"
" doc.getRange(\"a1\").setComment(\"DOB:\" + user.dateOfBirth)\n"
" doc.getRange(\"b1\").setValue(user.country + \"/\" + user.state + \"/\" + user.city);\n\n"
" var options =\n"
" {headers:{\n"
" \"Authorization\": 'Bearer ' + getFitbitService().getAccessToken(),\n"
" \"method\": \"GET\"\n"
" }};\n"
" var activities = [\"activities/log/steps\"];\n"
" var intradays = [\"activities-log-steps-intraday\"];\n\n"
" var lastIndex = 0;\n"
" for (var activity in activities) {\n"
" var index = 0;\n"
" var dateString = getFirstDate();\n"
" date = parseDate(dateString);\n"
" var table = new Array();\n"
" while (1) {\n"
" var currentActivity = activities[activity];\n"
" try {\n"
" var result = UrlFetchApp.fetch(\"https://api.fitbit.com/1/user/-/\" + currentActivity + \"/date/\" + dateString+ \"/\" + dateString + \".json\", options);\n"
" } catch(exception) {\n"
" Logger.log(exception);\n"
" }\n"
" var o = JSON.parse(result.getContentText());\n\n"
" var cell = doc.getRange('a3');\n"
" var titleCell = doc.getRange(\"a2\");\n"
" titleCell.setValue(\"Date\");\n"
" var title = currentActivity.split(\"/\");\n"
" title = title[title.length - 1];\n"
" titleCell.offset(0, 1 + activity * 1.0).setValue(title);\n"
" var row = o[intradays[activity]][\"dataset\"];\n"
" for (var j in row) {\n"
" var val = row[j];\n"
" var arr = new Array(2);\n"
" arr[0] = dateString + ' ' + val[\"time\"];\n"
" arr[1] = val[\"value\"];\n"
" table.push(arr);\n"
" // set the value index index\n"
" index++;\n"
" }\n"
" date.setDate(date.getDate()+1);\n"
" dateString = Utilities.formatDate(date, \"GMT\", \"yyyy-MM-dd\");\n"
" if (dateString > getLastDate()) {\n"
" break;\n"
" }\n\n"
" }\n"
" \n"
" // Batch set values of table, much faster than doing each time per loop run, this wouldn't work as is if there were multiple activities being listed\n"
" doc.getRange(\"A3:B\"+(table.length+2)).setValues(table);\n"
" }\n"
"}\n"
"// parse a date in yyyy-mm-dd format\n"
"function parseDate(input) {\n"
" var parts = input.match(/(\\d+)/g);\n"
" // new Date(year, month [, date [, hours[, minutes[, seconds[, ms]]]]])\n"
" return new Date(parts[0], parts[1]-1, parts[2]); // months are 0-based\n"
"}\n\n"
"// parse a date in 2011-10-25T23:57:00.000 format\n"
"function parseDate2(input) {\n"
" var parts = input.match(/(\\d+)/g);\n"
" return new Date(parts[0], parts[1]-1, parts[2], parts[3], parts[4]);\n"
"}")
subst = "\\2'\\4\\5\\8"
result = regex.sub(subst, test_str)
if result:
print(result)
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Python, please visit: https://docs.python.org/3/library/re.html