From fd9ec4851119a46f072c86a771ffdb593cede2a8 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Thu, 9 Apr 2026 20:57:46 -0400 Subject: [PATCH] Implement settings (via Clay) --- .gitignore | 2 ++ package.json | 21 +++++++++++++-------- src/c/main.c | 14 +++++--------- src/pkjs/config.js | 37 +++++++++++++++++++++++++++++++++++++ src/pkjs/index.js | 25 +++++++++++++++---------- 5 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 src/pkjs/config.js diff --git a/.gitignore b/.gitignore index b41ca9b..e14efc4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /.clangd /build /.lock* +/node_modules +/package-lock.json diff --git a/package.json b/package.json index 7f49a6a..072c7dc 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,29 @@ { "author": "RandyTheSilly", - "dependencies": {}, + "dependencies": { + "@rebble/clay": "^1.0.8" + }, "keywords": [ "jellyfin", "plex", - "sleep" + "sleep", + "timeline", + "health" ], "capabilities": [ - "health" + "health", + "configurable" ], "name": "1-more-episode", "pebble": { "displayName": "1 More Episode", "enableMultiJS": true, "messageKeys": [ - "JS_READY", - "SLEEP_TIMESTAMP", - "API_IS_PLEX", - "API_KEY", - "API_HOST" + "CLAY_API_HOST", + "CLAY_API_KEY", + "CLAY_API_IS_JELLYFIN", + "PKJS_READY", + "PKJS_SLEEP_TIMESTAMP" ], "projectType": "native", "resources": { diff --git a/src/c/main.c b/src/c/main.c index 05a65d1..6e5ee4a 100644 --- a/src/c/main.c +++ b/src/c/main.c @@ -16,32 +16,28 @@ static TextLayer *s_pin_notice_layer; // declare time tracking statics static time_t s_sleep_timestamp; -static void send_to_pkjs() { +static void send_sleep_time_to_pkjs() { DictionaryIterator *out; AppMessageResult result = app_message_outbox_begin(&out); if (result != APP_MSG_OK) { text_layer_set_text(s_last_episode_layer, "outbox_begin failure"); return; } - dict_write_uint32(out, MESSAGE_KEY_SLEEP_TIMESTAMP, s_sleep_timestamp); - dict_write_uint8(out, MESSAGE_KEY_API_IS_PLEX, 0); - dict_write_cstring(out, MESSAGE_KEY_API_KEY, ""); - dict_write_cstring(out, MESSAGE_KEY_API_HOST, ""); - + dict_write_uint32(out, MESSAGE_KEY_PKJS_SLEEP_TIMESTAMP, s_sleep_timestamp); result = app_message_outbox_send(); if (result != APP_MSG_OK) { - text_layer_set_text(s_last_episode_layer, "outbox_send failure "); + text_layer_set_text(s_last_episode_layer, "outbox_send failure"); return; } } static void inbox_received_handler(DictionaryIterator *iter, void *context) { - Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_JS_READY); + Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_PKJS_READY); if (ready_tuple) { s_js_ready = true; } APP_LOG(APP_LOG_LEVEL_INFO, "Received JS_READY, calling PKJS..."); - send_to_pkjs(); + send_sleep_time_to_pkjs(); } static void inbox_dropped_handler(AppMessageResult reason, void *context) { diff --git a/src/pkjs/config.js b/src/pkjs/config.js new file mode 100644 index 0000000..a87cfa2 --- /dev/null +++ b/src/pkjs/config.js @@ -0,0 +1,37 @@ +module.exports = [ + { + "type": "heading", + "defaultValue": "1 More Episode | Settings" + }, + { + "type": "section", + "items": [ + { + "type": "heading", + "defaultValue": "API Credentials" + }, + { + "type": "input", + "messageKey": "CLAY_API_HOST", + "label": "API Host", + "description": "Example: https://jellyfin.example.com" + }, + { + "type": "input", + "messageKey": "CLAY_API_KEY", + "label": "API Key" + }, + { + "type": "toggle", + "messageKey": "CLAY_API_IS_JELLYFIN", + "defaultValue": true, + "label": "Jellyfin Support", + "description": "Toggle off if using Plex. If using Jellyfin, leave on :D" + } + ] + }, + { + "type": "submit", + "defaultValue": "Save Settings" + } +]; diff --git a/src/pkjs/index.js b/src/pkjs/index.js index f5dbc22..cdeec27 100644 --- a/src/pkjs/index.js +++ b/src/pkjs/index.js @@ -1,24 +1,29 @@ +var Clay = require('@rebble/clay'); +var clayConfig = require('./config'); +var clay = new Clay(clayConfig); + Pebble.addEventListener("ready", function () { - Pebble.sendAppMessage({ JS_READY: 1 }); + Pebble.sendAppMessage({ PKJS_READY: 1 }); }); Pebble.addEventListener("appmessage", function (dict) { - if (dict.payload["API_HOST"]) { - if (dict.payload["API_IS_PLEX"] == 0) { - callAPI(dict.payload["API_HOST"] + "/System/ActivityLog/Entries", false, dict.payload["API_KEY"]); + if (dict.payload["PKJS_SLEEP_TIMESTAMP"]) { + var sleepTimestamp = dict.payload["PKJS_SLEEP_TIMESTAMP"]; + var cfg = JSON.parse(localStorage.getItem('clay-settings')); + // TODO report last episode as "Configure app settings!" if CLAY_API_HOST or CLAY_API_KEY is empty + if (cfg.CLAY_API_IS_JELLYFIN == true) { + callAPI(cfg.CLAY_API_HOST + "/System/ActivityLog/Entries", cfg.CLAY_API_KEY, true, sleepTimestamp); } 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(dict.payload["API_HOST"] + "/status/sessions/history/all", true, dict.payload["API_KEY"]); - callAPI(dict.payload["API_HOST"] + "/api/v2?apikey=" + dict.payload["API_KEY"] + "&cmd=get_history", true, NULL); + //callAPI(cfg.CLAY_API_HOST + "/status/sessions/history/all", cfg.CLAY_API_KEY, false, dict.payload["API_KEY"], sleepTimestamp); + callAPI(cfg.CLAY_API_HOST + "/api/v2?apikey=" + cfg.CLAY_API_KEY + "&cmd=get_history", null, false, sleepTimestamp); } } }); -function callAPI(fullURL, isPlex, apiKey) { - console.log("callAPI URL:", fullURL, "isPlex:", isPlex); - +function callAPI(fullURL, apiKey, isJellyfin, sleepTimestamp) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { @@ -28,7 +33,7 @@ function callAPI(fullURL, isPlex, apiKey) { xhr.open("GET", fullURL, true); xhr.setRequestHeader("Accept", "application/json"); - if (!isPlex) { + if (isJellyfin) { xhr.setRequestHeader("Authorization", 'MediaBrowser Token="' + apiKey + '"'); }