var Clay = require('@rebble/clay'); var clayConfig = require('./config'); var customClay = require('./customClay'); new Clay(clayConfig, customClay); Pebble.addEventListener("ready", function () { Pebble.sendAppMessage({ PKJS_READY: 1 }); }); Pebble.addEventListener("appmessage", function (dict) { if (dict.payload["PKJS_SLEEP_TIMESTAMP"]) { const sleepTimestamp = dict.payload["PKJS_SLEEP_TIMESTAMP"]; const cfg = JSON.parse(localStorage.getItem('clay-settings')); // report to user if some configuration is missing if (!cfg || cfg.CLAY_API_HOST == "" || cfg.CLAY_API_KEY == "" || cfg.CLAY_USER == "") { Pebble.sendAppMessage({ PKJS_LAST_WATCHED: "SOME APP SETTINGS ARE UNSET" }); } if (cfg.CLAY_API_IS_JELLYFIN == true) { callAPI(cfg.CLAY_API_HOST + "/System/ActivityLog/Entries?hasUserId=true&limit=100", cfg.CLAY_API_KEY, true, cfg.CLAY_USER, sleepTimestamp * 1000); } else { // The official history endpoint doesn't seem to return history w/o Plex Pass. // If someone with Plex Pass wants to give it a shot, I'd be happy to accept a PR adding this as an option. // Until then, I'm using Tautulli because it's free. //callAPI(cfg.CLAY_API_HOST + "/status/sessions/history/all", cfg.CLAY_API_KEY, false, cfg.CLAY_USER, sleepTimestamp); callAPI(cfg.CLAY_API_HOST + "/api/v2?apikey=" + cfg.CLAY_API_KEY + "&cmd=get_history&length=100", null, false, cfg.CLAY_USER, sleepTimestamp); } } if (dict.payload["PKJS_PIN_TIMESTAMP"] && dict.payload["PKJS_PIN_TITLE"]) { var pin = { id: dict.payload["PKJS_PIN_TIMESTAMP"].toString(), time: new Date(dict.payload["PKJS_PIN_TIMESTAMP"] * 1000).toISOString(), layout: { type: "genericPin", title: dict.payload["PKJS_PIN_TITLE"] } }; Pebble.insertTimelinePin(JSON.stringify(pin)); } }); function callAPI(fullURL, apiKey, isJellyfin, trackedUser, sleepTimestamp) { const xhr = new XMLHttpRequest(); let didReportError = false; function reportApiError(message) { if (didReportError) { return; } didReportError = true; Pebble.sendAppMessage({ PKJS_LAST_WATCHED: message }); } xhr.onerror = function () { reportApiError("API UNREACHABLE"); }; xhr.ontimeout = function () { reportApiError("API TIMEOUT"); }; xhr.onreadystatechange = function () { if (xhr.readyState === 4) { switch (xhr.status) { case 200: break; case 0: reportApiError("API UNREACHABLE"); return; case 401: case 403: reportApiError("API ERROR: " + xhr.status + " (CHECK API KEY)"); return; case 404: case 405: reportApiError("API ERROR: " + xhr.status + " (INVALID ENDPOINT?)"); return; default: reportApiError("API ERROR: " + xhr.status); } if (!xhr.responseText) { reportApiError("API EMPTY RESPONSE"); return; } let resp; try { resp = JSON.parse(xhr.responseText); } catch (e) { reportApiError("API INVALID RESPONSE"); return; } if (resp && ((isJellyfin === true && Array.isArray(resp.Items)) || (isJellyfin === false && Array.isArray(resp.response.data.data)))) { let delta; let bestDelta = Infinity; let lastWatched = ""; if (isJellyfin === true) { const re = /^(.+) is playing (.+) on .*$/; let arr; let logTimestamp; resp.Items.forEach(function (item) { arr = re.exec(item.Name); if (arr != null && arr[1] == trackedUser) { logTimestamp = Date.parse(item.Date); if (!Number.isNaN(logTimestamp)) { delta = sleepTimestamp - logTimestamp; if (delta >= 0 && delta < bestDelta) { bestDelta = delta; lastWatched = arr[2]; } } } }); } else { resp.response.data.data.forEach(function (item) { if (item.user == trackedUser) { // we use "date" instead of "started" because started tracks the first // time the user watched the media, not just the start of the last session. delta = sleepTimestamp - item.date; if (delta >= 0 && delta < bestDelta) { bestDelta = delta; lastWatched = item.full_title; } } }); } if (lastWatched != "") { Pebble.sendAppMessage({ PKJS_LAST_WATCHED: lastWatched }); } else { Pebble.sendAppMessage({ PKJS_LAST_WATCHED: "NO WATCH HISTORY FOUND FOR USER " + trackedUser }); } } } }; xhr.open("GET", fullURL, true); xhr.timeout = 8000; xhr.setRequestHeader("Accept", "application/json"); if (isJellyfin) { xhr.setRequestHeader("Authorization", 'MediaBrowser Token="' + apiKey + '"'); } xhr.send(null); }