Add Record Until to WebUI (@o8o8o8o8o8o8o8o8o8o8o8o8)

This commit is contained in:
Jafea7 2025-05-14 22:07:28 +10:00
parent 3ac3f83ad4
commit d55d2d5b60
2 changed files with 179 additions and 20 deletions

View File

@ -7,9 +7,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes">
<meta name="description" content="CTB Recorder is a free recording software for Chaturbate">
<meta name="author" content="">
<meta name="version" content="${project.version}">
<meta name="version" content="5.3.2">
<title>CTB Recorder ${project.version}</title>
<title>CTB Recorder 5.3.2</title>
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
@ -87,8 +87,37 @@
<div class="col-lg-10 mx-auto">
<div class="form-group">
<label for="addModelByUrl">Add Model</label>
<input type="text" class="form-control" id="addModelByUrl"
placeholder="e.g. MyFreeCams:ModelName or an URL like https://chaturbate.com/modelname/" onKeyUp="addModelKeyPressed(event)">
<div class="input-group">
<input type="text" class="form-control" id="addModelByUrl"
placeholder="e.g. MyFreeCams:ModelName or an URL like https://chaturbate.com/modelname/" onKeyUp="addModelKeyPressed(event)">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="toggleStopAtOptions">
<i class="fa fa-clock"></i>
</button>
<button class="btn btn-primary" type="button" onclick="addModel()">
Add
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Stop At Options - Initially hidden -->
<div class="row" id="stopAtOptionsRow" style="display: none;">
<div class="col-lg-10 mx-auto">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">Stop at</span>
</div>
<input type="datetime-local" class="form-control" id="recordUntilDate">
<div class="input-group-append">
<select class="form-control" id="recordUntilAction">
<option value="REMOVE">REMOVE</option>
<option value="PAUSE">PAUSE</option>
</select>
</div>
</div>
</div>
</div>
</div>
@ -111,7 +140,7 @@
<td><a data-bind="attr: { href: ko_url, title: ko_name }, text: ko_name"></a></td>
<td><span data-bind="checked: ko_online, class: ko_online() ? `fa fa-check-square checkmark-green` : ``"
style="font-size: 2em"></span></td>
<td><span data-bind="checked: ko_recording, class: ko_recording() ? `fa fa-circle red` : ``" style="font-size: 2em"></span></td>
<td><span data-bind="checked: ko_recording, class: ko_recording() ? `fa fa-circle red` : ``" style="font-size: 2em; width: 40px; display: inline-block; text-align: center;"></span><span data-bind="if: ko_recordUntil && ko_recordUntil() !== undefined && ko_recordUntil() !== null && ko_recordUntil() !== 9000000000000000000"><i class="fa fa-clock" title="Scheduled stop time" style="font-size: 2em; color: #ffffff;"></i></span></td>
<td>
<button class="btn btn-secondary fa fa-play" title="Resume recording"
data-bind="click: ctbrec.resume, visible: ko_suspended"></button>
@ -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 {

View File

@ -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);
}
}
}
}