sleepsecure

A lightweight scraper for SleepCycle's online SleepSecure data.

Usage no npm install needed!

<script type="module">
  import sleepsecure from 'https://cdn.skypack.dev/sleepsecure';
</script>

README

sleepsecure

One of my favourite smartphone apps is SleepCycle; it records details of your sleep-quality using your phone's microphone and accelerometer, and tracks changes in that quality over time.

In addition, they offer a paid service that uploads your sleep-data to their servers, titled “SleepSecure.” Unfortunately — despite repeated inquiries over the last six(!) years — Northcube has never found the time or developer resources to expose any sort of official API for that sleep- data. )=

In the interim, thus, I've written a little scraping-tool: given a SleepSecure login and password, I can extract sleep-data via HTML-scraping of the SleepSecure dashboard.

Caveats

It's important to understand that this is not an API client. There is no official SleepSecure API. This is a scraping tool, which means that it's hitting Northcube's servers in a way for which they were not designed.

Based simply on the load-time of the SleepSecure dashboard, I'm pretty sure their web-app isn't exactly performance-optimized — and I have no idea what sort of server resources they're paying for. Take a gander at the “Basic Web Scraping Etiquette” section of Sebastian Wain's ‘Ultimate Guide to Web Scraping’; and attempt some backing-off behaviour if requesting information from their servers fairly often.

(You reading this, Northcube? Feel free to open an Issue if you'd prefer this operated in a different way! I'm happy to cooperate! <3)

Usage

This module exposes a single class; let's call it Session:

import SleepSecureSession from 'sleepsecure'

Each Session requires log-in information:

const sss = new SleepSecureSession('cool_dude@gmail.com', 'snicker snicker sekrit')

One of the primary purposes of the library is to handle persistence of the login cookies necessary to make requests, and re-authentication whenever that token expires. Generally speaking, you don't need to explicitly instruct the library to log-in — however, if you want to pre-emptively ensure logging-in is successful, you can explicitly issue a call to ::login():

if (!(await sss.login()))
   console.error("Unable to log in! Double-check your username and password?")

The cookies default to being stored according to the XDG spec (generally, under ~/.cache); but a specific filename can be provided as configuration:

new SleepSecureSession('someone', 'wizardry', { cookie_store_path: '~/.sleepsecure.txt' })

More specific methods are presumably forthcoming; but at the moment, the only interface to SleepSecure's data that is provided is a wrapper around bhttp's ::request() function, that additionally handles authentication and session-management:

sss.request("/site/comp/calendar")
.then(function(response){
   const $ = cheerio.load(response.body)

   $('tr:not(:nth-child(1))', 'table').each(function(){
      const date = $('.description > a', this).text()
          , quality = $('.value', this).first().text()

      console.log(`On ${date}, my sleep quality was ${quality}.`) }) })