Last active
May 23, 2024 06:01
-
-
Save tai-sho/32ea89f0be8b595f2e616542e39b6d69 to your computer and use it in GitHub Desktop.
Get sleep and workout score of Oura Ring by Google Apps Script and register it to google calendar. Refer: https://tech.affordigitalife.com/oura-api-sleep-log/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Refer to https://tech.affordigitalife.com/oura-api-sleep-log/ | |
*/ | |
function main(){ | |
const days = 20; | |
for (let i = 0; i < days; i++) { | |
let today = new Date() | |
today.setDate(today.getDate() - i) | |
let yesterday = new Date() | |
yesterday.setDate(yesterday.getDate() - (i + 1)) | |
let scheduleCount = getScheduleCounts(today) | |
console.log(scheduleCount) | |
if (scheduleCount.workout === 0) { | |
setWorkoutForDay(today, yesterday) | |
} | |
if (scheduleCount.sleep === 0) { | |
setSleepForDay(today, yesterday) | |
} | |
} | |
} | |
function connectOuraAPI(api, parameters) { | |
const token = getProperty('OURA_API_KEY') | |
const baseUrl = 'https://api.ouraring.com/v2/usercollection/' | |
let url = `${baseUrl}${api}` | |
url = setQueryParameter(url, parameters) | |
let requestOptions = { | |
muteHttpExceptions: true, | |
method: 'GET', | |
headers: { | |
'Authorization': `Bearer ${token}` | |
} | |
} | |
let res = UrlFetchApp.fetch(url, requestOptions).getContentText() | |
console.log(res) | |
return JSON.parse(res) | |
} | |
function setQueryParameter(url, parameters) { | |
url += '?'; | |
for (let parameter in parameters){ | |
url += `${parameter}=${parameters[parameter]}&` | |
if(Object.keys(parameters).slice(-1)[0] === parameter){ | |
url = url.slice(0, -1) | |
} | |
} | |
return url; | |
} | |
function getSleep(start_date, end_date) { | |
return connectOuraAPI('sleep', { | |
start_date: formatDate(start_date), | |
end_date: formatDate(end_date) | |
}) | |
} | |
function getSleepScore(start_date, end_date) { | |
return connectOuraAPI('daily_sleep', { | |
start_date: formatDate(start_date), | |
end_date: formatDate(end_date) | |
}) | |
} | |
function getWorkout(start_date, end_date) { | |
return connectOuraAPI('workout', { | |
start_date: formatDate(start_date), | |
end_date: formatDate(end_date) | |
}) | |
} | |
function addSleepEvent(score, bedtime, awakeTime, description = '') { | |
const label = getSleepLabel() | |
addEventForGoogleCalendar(`${label}:${score}`, bedtime, awakeTime, description, 4) | |
} | |
function addWorkoutEvent(activity, start, finish, description = '') { | |
const label = getWorkoutLabel() | |
addEventForGoogleCalendar(`${label}:${activity}`, start, finish, description, 2) | |
} | |
function addEventForGoogleCalendar(title, startDate, endDate, description, color) { | |
return getCalendar() | |
.createEvent(title, new Date(startDate), new Date(endDate), { | |
description: description | |
}) | |
.setColor(color) | |
} | |
function getEventForDayGoogleCalendar(date) { | |
return getCalendar().getEventsForDay(date) | |
} | |
function getCalendar() { | |
const CALENDAR_ID = getProperty('GOOGLE_CALENDAR_ID_OURA') | |
return CalendarApp.getCalendarById(CALENDAR_ID) | |
} | |
function getScheduleCounts(today) { | |
let events = getEventForDayGoogleCalendar(today) | |
let counts = {sleep: 0, workout: 0, date: today} | |
for (let e of events) { | |
let title = e.getTitle() | |
if (title.startsWith(getSleepLabel())) { | |
counts.sleep++ | |
} else if (title.startsWith(getWorkoutLabel())) { | |
counts.workout++ | |
} | |
} | |
return counts; | |
} | |
function setWorkoutForDay(today, yesterday) { | |
console.log(['workout', today, yesterday]); | |
let workout = getWorkout(yesterday, today) | |
if (!workout.data[0]) { | |
console.log('workout is not found'); | |
return 0; | |
} | |
let activity = workout.data[0].activity | |
for (let w of workout.data){ | |
console.log(w) | |
addWorkoutEvent(activity, w.start_datetime, w.end_datetime, JSON.stringify(workout)) | |
} | |
return workout.data.length; | |
} | |
function setSleepForDay(today, yesterday) { | |
console.log(['sleep', today, yesterday]); | |
let sleep = getSleep(yesterday, today) | |
let dailySleep = getSleepScore(yesterday, today) | |
if (!dailySleep.data[0]) { | |
console.log('sleep is not found'); | |
return 0; | |
} | |
let dailySleepScore = dailySleep.data[0].score | |
for (let s of sleep.data){ | |
console.log(s) | |
addSleepEvent(dailySleepScore, s.bedtime_start, s.bedtime_end, JSON.stringify(sleep) + '\n' + JSON.stringify(dailySleep)) | |
} | |
return sleep.data.length; | |
} | |
function getSleepLabel() { | |
return 'Sleep' | |
} | |
function getWorkoutLabel() { | |
return 'Workout' | |
} | |
function getProperty(key) { | |
const prop = PropertiesService.getScriptProperties(); | |
return prop.getProperty(key); | |
} | |
function formatDate(date) { | |
return Utilities.formatDate(date, 'JST', 'yyyy-MM-dd'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment