// This code is licensed under the same terms as Habitica: // https://raw.githubusercontent.com/HabitRPG/habitrpg/develop/LICENSE /* ========================================== */ /* [Users] Required script data to fill in */ /* ========================================== */ const USER_ID = "PasteYourUserIdHere"; const API_TOKEN = "PasteYourApiTokenHere"; // Do not share this to anyone const WEB_APP_URL = "PasteGeneratedWebAppUrlHere"; /* ========================================== */ /* [Users] Required customizations to fill in */ /* ========================================== */ // Which version do you want to use? // If you want to heal a set number when leveling up (such as 4.5 HP), select 2. // If you want to heal a percent of your remaining health (such as 25%), select 3. const VERSION = 2; // How much HP do you want to gain each level-up? Fill in the correct one (set value or percent of remaining health) const HP_SET_VALUE_PER_LEVEL = 4.5; // Enter a number between 0 and 50. const HP_PERCENT_PER_LEVEL = 50.0; // Do not put a percent sign after the number here. Enter a number between 0 and 100. /* ========================================== */ /* [Users] Optional customizations to fill in */ /* ========================================== */ /* ========================================== */ /* [Users] Do not edit code below this line */ /* ========================================== */ const AUTHOR_ID = "0034eb14-b4d8-494e-8386-d3f33cff7922"; const SCRIPT_NAME = "Partial Healing"; const HEADERS = { "x-client" : AUTHOR_ID + " - " + SCRIPT_NAME, "x-api-user" : USER_ID, "x-api-key" : API_TOKEN, } const scriptProperties = PropertiesService.getScriptProperties(); // Constants can have properties changed const HP_KEY = "HP_KEY"; const LVL_KEY = "LVL_KEY"; const TIMESTAMP_KEY = "TIMESTAMP_KEY"; var hpKey = ""; var lvlKey = ""; var timestampKey = ""; function doOneTimeSetup() { // create the webhook const options = { "scored" : true, } const payload = { "url" : WEB_APP_URL, "label" : SCRIPT_NAME + " Webhook", "type" : "taskActivity", "options" : options, } apiMult_createNewWebhookNoDuplicates(payload); // set script properties so they carry over to next session initScriptProperties(); } // do things when the webhook runs function doPost(e) { const dataContents = JSON.parse(e.postData.contents); const type = dataContents.type; if (type == "scored") { var timestampKey = TIMESTAMP_KEY; var timeStart = Number(scriptProperties.getProperty(timestampKey)); if ( (timeStart == 0) || (timeStart == "") || (timeStart == undefined) || (timeStart == null) ) { timeStart = Date.now(); } var timeEnd = Date.now(); // Rate limiting: only grab HP and LVL if it's been 5 seconds between clicks if ( (timeEnd - timeStart) >= 5000 ) { var hpKey = HP_KEY; var lvlKey = LVL_KEY; var prevHp = Number(scriptProperties.getProperty(hpKey)); var prevLvl = Number(scriptProperties.getProperty(lvlKey)); const response = api_getAuthenticatedUserProfile("stats"); user = JSON.parse(response).data; var currentHp = user.stats.hp; var currentLvl = user.stats.lvl; // See if they've leveled up if (currentLvl > prevLvl) { if ( VERSION == 2 ) { var valueToHeal = sanitizeInput (HP_SET_VALUE_PER_LEVEL, 0, 50); var newHp = valueToHeal + prevHp; if (newHp >= 50) { api_updateUser({"stats.hp" : 50}); } else { api_updateUser({"stats.hp" : newHp}); } prevHp = newHp; prevLvl = currentLvl; } else if ( VERSION == 3 ) { var percentToHeal = sanitizeInput (HP_PERCENT_PER_LEVEL, 0, 100); var healing = ( percentToHeal / 100 ) * ( 50 - prevHp ); var newHpPercent = healing + prevHp; if (newHpPercent >= 50) { api_updateUser({"stats.hp" : 50}); } else { api_updateUser({"stats.hp" : newHpPercent}); } prevHp = newHp; prevLvl = currentLvl; } } else { // If previous and current HP are the same, no need to re-save if (prevHp != currentHp) { prevHp = currentHp; } } // Save values to non-volatile memory timeStart = timeEnd; scriptProperties.setProperty(hpKey, prevHp); scriptProperties.setProperty(lvlKey, prevLvl); scriptProperties.setProperty(timestampKey, timeStart); return HtmlService.createHtmlOutput(); } } } // Create a webhook if no duplicate exists function apiMult_createNewWebhookNoDuplicates(payload) { const response = api_getWebhooks(); const webhooks = JSON.parse(response).data; var duplicateExists = 0; for (var i in webhooks) { if (webhooks[i].label == payload.label) { duplicateExists = 1; } } // If webhook to be created doesn't exist yet if (!duplicateExists) { api_createNewWebhook(payload); } } // Used to see existing webhooks, and therefore if there's a duplicate function api_getWebhooks() { const params = { "method" : "get", "headers" : HEADERS, "muteHttpExceptions" : true, } const url = "https://habitica.com/api/v3/user/webhook"; return UrlFetchApp.fetch(url, params); } // Creates a webhook (as part of the "don't make it if there's a duplicate" function) function api_createNewWebhook(payload) { const params = { "method" : "post", "headers" : HEADERS, "contentType" : "application/json", "payload" : JSON.stringify(payload), "muteHttpExceptions" : true, } const url = "https://habitica.com/api/v3/user/webhook"; return UrlFetchApp.fetch(url, params); } // Gets user info so I can use it, especially stats like mana, experience, and level function api_getAuthenticatedUserProfile(userFields) { const params = { "method" : "get", "headers" : HEADERS, "muteHttpExceptions" : true, } var url = "https://habitica.com/api/v3/user"; if (userFields != "") { url += "?userFields=" + userFields; } return UrlFetchApp.fetch(url, params); } // Sets initial properties that will be used/saved later. function initScriptProperties() { const responseInit = api_getAuthenticatedUserProfile("stats"); user = JSON.parse(responseInit).data; var currentHp = user.stats.hp; var currentLvl = user.stats.lvl; var timestampInit = Date.now(); scriptProperties.setProperty(HP_KEY, currentHp); scriptProperties.setProperty(LVL_KEY, currentLvl); scriptProperties.setProperty(TIMESTAMP_KEY, timestampInit); } function sanitizeInput (input, minimum, maximum) { if ( input < minimum ) { return minimum; } else if ( input > maximum ) { return maximum; } else { return input; } } function api_updateUser(payload) { const params = { "method" : "put", "headers" : HEADERS, "contentType" : "application/json", "payload" : JSON.stringify(payload), "muteHttpExceptions" : true, } const url = "https://habitica.com/api/v3/user"; return UrlFetchApp.fetch(url, params); }