From 7b2cb3e04202bcf8bbf55f8721c15ffc5dc6b840 Mon Sep 17 00:00:00 2001 From: BlipRanger <1860540+BlipRanger@users.noreply.github.com> Date: Sun, 16 Jul 2023 13:03:37 -0400 Subject: [PATCH] Getter/setters, get/update, WIP frontend --- public/script.js | 81 ++++++++++++++++++++++++++++++++++++++++++++++-- server.js | 71 +++++++++++++----------------------------- statsHelpers.js | 10 ++++++ 3 files changed, 110 insertions(+), 52 deletions(-) diff --git a/public/script.js b/public/script.js index 193e80c37..f1e94d89a 100644 --- a/public/script.js +++ b/public/script.js @@ -325,6 +325,7 @@ let crop_data = undefined; let is_delete_mode = false; let fav_ch_checked = false; let scrollLock = false; +export let charStats = {}; //initialize global var for future cropped blobs let currentCroppedAvatar = ''; @@ -951,10 +952,10 @@ async function getCharacters() { await getGroups(); await printCharacters(); - await AA_CountCharTime(this_chid); updateCharacterCount('#rm_print_characters_block > div'); + await AA_CountCharTime(this_chid); } } @@ -1308,6 +1309,8 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true const momentDate = timestampToMoment(mes.send_date); const timestamp = momentDate.isValid() ? momentDate.format('LL LT') : ''; + statMesProcess(mes, type); + if (mes?.extra?.display_text) { messageText = mes.extra.display_text; @@ -3695,6 +3698,59 @@ function cleanUpMessage(getMessage, isImpersonate, displayIncompleteSentences = return getMessage; } + +/** + * Calculates the time difference between two dates. + * + * @param {string} gen_started - The start time in ISO 8601 format. + * @param {string} gen_finished - The finish time in ISO 8601 format. + * @returns {number} - The difference in time in milliseconds. + */ +function calculateGenTime(gen_started, gen_finished) { + let startDate = new Date(gen_started); + let endDate = new Date(gen_finished); + return endDate - startDate; +} + +function updateStats() { + const response = fetch('/updatestats', { + method: 'POST', + headers: getRequestHeaders(), + body: JSON.stringify(charStats), + + }); + if (response.status !== 200) { + console.error('Failed to update stats'); + } +} + + +function statMesProcess(line, type){ + if(this_chid === undefined) { + console.log(charStats); + return; + } + + let stat = charStats[characters[this_chid].avatar]; + console.log(stat); // add this line to check the value of stat + + stat.total_gen_time += calculateGenTime(line.gen_started, line.gen_finished); + if(line.is_user) { + stat.user_msg_count++; + stat.user_word_count += line.mes.split(' ').length; + } + else { + stat.non_user_msg_count++; + stat.non_user_word_count += line.mes.split(' ').length; + } + + if(type === 'swipe') { + stat.total_swipe_count++; + } + stat.date_last_chat = Date.now(); + updateStats(); +} + function saveReply(type, getMessage, this_mes_is_name, title) { if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined || chat[chat.length - 1]['is_user'])) { @@ -4836,7 +4892,7 @@ async function getSettings(type) { } const data = await response.json(); - + getStats(); if (data.result != "file not find" && data.settings) { settings = JSON.parse(data.settings); if (settings.username !== undefined) { @@ -5062,6 +5118,27 @@ async function saveSettings(type) { }); } + +async function getStats() { + const response = await fetch("/getstats", { + method: "POST", + headers: getRequestHeaders(), + body: JSON.stringify({}), + cache: "no-cache", + }); + + if (!response.ok) { + toastr.error('Stats could not be loaded. Try reloading the page.'); + throw new Error('Error getting stats'); + } + + const data = await response.json(); + charStats = data; + console.log(charStats); + +} + + function setCharacterBlockHeight() { const $children = $("#rm_print_characters_block").children(); const originalHeight = $children.length * $children.find(':visible').first().outerHeight(); diff --git a/server.js b/server.js index a683286a6..97a088c7f 100644 --- a/server.js +++ b/server.js @@ -68,7 +68,7 @@ const utf8Encode = new TextEncoder(); const commandExistsSync = require('command-exists').sync; // impoort from statsHelpers.js -const statHelpers = require('./statsHelpers.js'); +const statsHelpers = require('./statsHelpers.js'); const characterCardParser = require('./src/character-card-parser.js'); const config = require(path.join(process.cwd(), './config.conf')); @@ -1272,63 +1272,34 @@ app.post("/getcharacters", jsonParser, function (request, response) { /** - * Handle a POST request to pull stats for a character. + * Handle a POST request to get the stats object * - * This function reads the stats for a character from the 'stats' object and sends it as a JSON response., + * This function returns the stats object that was calculated by the `calculateStats` function. * * * @param {Object} request - The HTTP request object. * @param {Object} response - The HTTP response object. * @returns {void} */ -app.post("/getcharacterstats", jsonParser, function (request, response) { - if (!request.body || !request.body.avatar_url) { - return response.sendStatus(400); - } - - if (request.body.avatar_url !== sanitize(request.body.avatar_url)) { - console.error('Malicious filename prevented'); - return response.sendStatus(403); - } - - const avatarName = request.body.avatar_url; - if (!stats[avatarName]) { - return response.sendStatus(400); - } - - return response.send(charStats[avatarName]); +app.post("/getstats", jsonParser, function (request, response) { + console.log(statsHelpers.charStats); + response.send(JSON.stringify(statsHelpers.getCharStats())); }); /** - * Handle a POST request to update stats for a character. - * - * This function takes the stat name, value, and character from the request body and updates the 'stats' object - * with the new value. It then sends the updated 'stats' object for the character as a JSON response - * + * Handle a POST request to update the stats object + * + * This function updates the stats object with the data from the request body. + * * @param {Object} request - The HTTP request object. * @param {Object} response - The HTTP response object. * @returns {void} - */ -app.post("/updatecharacterstats", jsonParser, function (request, response) { - if (!request.body || !request.body.avatar_url || !request.body.stat_name || !request.body.stat_value) { - return response.sendStatus(400); - } - - if (request.body.avatar_url !== sanitize(request.body.avatar_url)) { - console.error('Malicious filename prevented'); - return response.sendStatus(403); - } - - const avatarName = request.body.avatar_url; - if (!stats[avatarName]) { - return response.sendStatus(400); - } - - const statName = request.body.stat_name; - const statValue = request.body.stat_value; - stats[avatarName][statName] = statValue; - - return response.send(stats[avatarName]); + * +*/ +app.post("/updatestats", jsonParser, function (request, response) { + if (!request.body) return response.sendStatus(400); + statsHelpers.setCharStats(request.body); + return response.sendStatus(200); }); @@ -3665,17 +3636,17 @@ const setupTasks = async function () { loadClaudeTokenizer('src/claude.json'), ]); - await statHelpers.loadStatsFile(directories.chats, directories.characters); + await statsHelpers.loadStatsFile(directories.chats, directories.characters); // Set up event listeners for a graceful shutdown - process.on('SIGINT', statHelpers.writeStatsToFileAndExit); - process.on('SIGTERM', statHelpers.writeStatsToFileAndExit); + process.on('SIGINT', statsHelpers.writeStatsToFileAndExit); + process.on('SIGTERM', statsHelpers.writeStatsToFileAndExit); process.on('uncaughtException', (err) => { console.error('Uncaught exception:', err); - statHelpers.writeStatsToFileAndExit(); + statsHelpers.writeStatsToFileAndExit(); }); - setInterval(statHelpers.saveStatsToFile, 5 * 60 * 1000); + setInterval(statsHelpers.saveStatsToFile, 5 * 60 * 1000); console.log('Launching...'); diff --git a/statsHelpers.js b/statsHelpers.js index c068b1e67..13b2afd50 100644 --- a/statsHelpers.js +++ b/statsHelpers.js @@ -53,6 +53,7 @@ async function loadStatsFile(chatsPath, charactersPath) { throw err; // Rethrow the error if it's something we didn't expect } } + console.log('Stats loaded from file:', charStats); } // Function to save the stats to file @@ -163,6 +164,13 @@ const calculateStats = (chatsPath, item, index) => { return { [item]: stats }; } +function getCharStats() { + return charStats; +} + +function setCharStats(stats) { + charStats = stats; +} @@ -255,4 +263,6 @@ module.exports = { saveStatsToFile, loadStatsFile, writeStatsToFileAndExit, + getCharStats, + setCharStats, };