diff --git a/server/src/main/resources/html/static/index.html b/server/src/main/resources/html/static/index.html index 8702a270..5ba7a2cd 100644 --- a/server/src/main/resources/html/static/index.html +++ b/server/src/main/resources/html/static/index.html @@ -7,9 +7,9 @@ - + - CTB Recorder ${project.version} + CTB Recorder 5.3.2 @@ -87,8 +87,37 @@
- +
+ +
+ + +
+
+
+
+ + + @@ -111,7 +140,7 @@ - + @@ -293,24 +322,146 @@ }; let hmac; - function addModelKeyPressed(e) { - let charCode = (typeof e.which === "number") ? e.which : e.keyCode; + // Toggle visibility of stopAt options + $(document).ready(function() { + $('#toggleStopAtOptions').click(function() { + $('#stopAtOptionsRow').toggle(); + + // Set default datetime to current time + 1 hour when showing options + if ($('#stopAtOptionsRow').is(':visible') && !$('#recordUntilDate').val()) { + let now = new Date(); + now.setHours(now.getHours() + 1); + + // Format the date for datetime-local input + let year = now.getFullYear(); + let month = (now.getMonth() + 1).toString().padStart(2, '0'); + let day = now.getDate().toString().padStart(2, '0'); + let hours = now.getHours().toString().padStart(2, '0'); + let minutes = now.getMinutes().toString().padStart(2, '0'); + + $('#recordUntilDate').val(`${year}-${month}-${day}T${hours}:${minutes}`); + } + }); + }); + + // Function to add model (shared by Enter key and Add button) + function addModel() { let val = $('#addModelByUrl').val(); - let duration = $('#recordingDuration').val(); // Get the recording duration input - if (charCode === 13) { - // Check if a valid duration is provided - let durationMinutes = duration ? parseInt(duration) : undefined; - ctbrec.add(val, durationMinutes, function() { - $('#addModelByUrl').val(''); - $('#recordingDuration').val(''); // Clear the recording duration input - }); - } else { - $('#addModelByUrl').autocomplete({ - source: ["BongaCams:", "Cam4:", "Camsoda:", "Chaturbate:", "Dreamcam:", "Fc2Live:", "Flirt4Free:", "MyFreeCams:", "Showup:", "Streamate:", "Streamray:", "Stripchat:", "XloveCam:"] - }); - } + + if (!val) return; // Don't do anything if the input is empty + + // Store if we need to add stopAt parameters + let useStopAt = $('#stopAtOptionsRow').is(':visible') && $('#recordUntilDate').val(); + let stopAtDate = useStopAt ? $('#recordUntilDate').val() : null; + let stopAtAction = useStopAt ? $('#recordUntilAction').val() : null; + let modelInput = val; + + // Step 1: Add the model using the standard approach + ctbrec.add(val, undefined, function() { + console.log("Model added successfully"); + $('#addModelByUrl').val(''); + + if (useStopAt) { + // Step 2: After a delay, set stopAt parameters + setTimeout(function() { + // Extract model name from the input + let modelName = modelInput; + if (modelName.includes(':')) { + modelName = modelName.split(':')[1]; + } else if (modelName.includes('/')) { + modelName = modelName.split('/').filter(Boolean).pop(); + } + + console.log("Looking for model: " + modelName); + console.log("Models in array:", observableModelsArray()); + + // Try to find the model in the observableModelsArray + let existingModel = null; + + // Try various ways to find the model + for (let i = 0; i < observableModelsArray().length; i++) { + let model = observableModelsArray()[i]; + + if (model.name === modelName) { + existingModel = model; + break; + } + + if (model.ko_name && typeof model.ko_name === 'function' && model.ko_name() === modelName) { + existingModel = model; + break; + } + + // Check if URL contains the model name + if (model.url && model.url.includes(modelName)) { + existingModel = model; + break; + } + } + + if (!existingModel) { + console.log("Could not find the model. Creating a simple model object instead."); + // If we can't find the model, create a simple object with just the necessary properties + existingModel = { name: modelName }; + } + + // Add stopAt parameters to the model + // Always use milliseconds for recordUntil + let dateTimestamp = new Date(stopAtDate).getTime(); + existingModel.recordUntil = dateTimestamp; + existingModel.recordUntilSubsequentAction = stopAtAction; + + console.log("Using milliseconds for recordUntil. Value: " + existingModel.recordUntil); + + console.log("Model with stopAt parameters:", existingModel); + + // Send the stopAt action + let stopAtMsg = '{"action": "stopAt", "model": ' + JSON.stringify(existingModel) + '}'; + + $.ajax({ + type: 'POST', + url: '../rec', + dataType: 'json', + async: true, + timeout: 60000, + headers: {'CTBREC-HMAC': CryptoJS.HmacSHA256(stopAtMsg, hmac)}, + data: stopAtMsg + }) + .done(function(data) { + console.log("StopAt response:", data); + if (data.status === 'success') { + // Use simple date formatting + let date = new Date(stopAtDate).toLocaleString(); + $.notify('Recording will stop at ' + date, 'info'); + + // Reset the datetime input and hide the options + $('#recordUntilDate').val(''); + $('#stopAtOptionsRow').hide(); + } else { + $.notify('Setting stopAt parameters failed', 'error'); + } + }) + .fail(function(jqXHR, textStatus, errorThrown) { + console.log(textStatus, errorThrown); + $.notify('Setting stopAt parameters failed', 'error'); + }); + }, 3000); // Wait 3 seconds to make sure the model is registered + } + }); } + function addModelKeyPressed(e) { + let charCode = (typeof e.which === "number") ? e.which : e.keyCode; + + if (charCode === 13) { + addModel(); + } else { + $('#addModelByUrl').autocomplete({ + source: ["AmateurTv:", "BongaCams:", "Cam4:", "Camsoda:", "Chaturbate:", "CherryTv:", "Dreamcam:", "Fc2Live:", "Flirt4Free:", "LiveJasmin:", "MVLive:", "MyFreeCams:", "SecretFriends:", "Showup:", "Streamate:", "Streamray:", "Stripchat:", "XloveCam:"] + }); + } + } + let ctbrec = { add: function(input, duration, onsuccess) { try { diff --git a/server/src/main/resources/html/static/models.js b/server/src/main/resources/html/static/models.js index 50e08cf3..8244f0c0 100644 --- a/server/src/main/resources/html/static/models.js +++ b/server/src/main/resources/html/static/models.js @@ -68,6 +68,7 @@ function syncModels(models) { model.ko_recording = ko.observable(model.online && !model.suspended); //model.ko_recording_class = ko.observable( (model.online && !model.suspended) ? 'fa fa-circle red' : '' ); model.ko_suspended = ko.observable(model.suspended); + model.ko_recordUntil = ko.observable(model.recordUntil); model.swallowEvents = false; model.ko_suspended.subscribe(function(checked) { if (model.swallowEvents) { @@ -98,6 +99,13 @@ function syncModels(models) { m.ko_suspended(model.suspended); m.swallowEvents = false; m.ko_recording(m.ko_online() && !m.ko_suspended()); + + // Update the recordUntil property to ensure clock icon refreshes + if (m.ko_recordUntil && typeof m.ko_recordUntil === 'function') { + m.ko_recordUntil(model.recordUntil); + } else { + m.ko_recordUntil = ko.observable(model.recordUntil); + } } } }