Add Record Until to WebUI
This commit is contained in:
parent
90c887a4dc
commit
2bf6e9787a
|
@ -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>
|
||||
|
@ -210,7 +239,14 @@
|
|||
<tbody data-bind="foreach: settings">
|
||||
<tr>
|
||||
<td data-bind="text: name"></td>
|
||||
<td><input class="form-control" data-bind="value: value" style="width: 100%"/></td>
|
||||
<td>
|
||||
<div data-bind="ifnot: type === 'STRING_LIST'">
|
||||
<input class="form-control" data-bind="value: ko_value" style="width: 100%;" />
|
||||
</div>
|
||||
<div data-bind="if: type === 'STRING_LIST'">
|
||||
<textarea rows="3" class="form-control" data-bind="value: ko_value" style="width: 100%;"></textarea>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -286,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 {
|
||||
|
|
|
@ -44,20 +44,17 @@ function isModelInArray(array, model) {
|
|||
* Synchronizes models from the server with the displayed knockout model table
|
||||
*/
|
||||
function syncModels(models) {
|
||||
// remove models from the observable array, which are not in the
|
||||
// updated list
|
||||
for ( let idx in observableModelsArray()) {
|
||||
let model = observableModelsArray()[idx];
|
||||
if (!isModelInArray(models, model)) {
|
||||
observableModelsArray.remove(model);
|
||||
}
|
||||
}
|
||||
// remove models from the observable array, which are not in the updated list
|
||||
var newModelsMap = new Map(models.map(m => [m.url, m]));
|
||||
observableModelsArray.remove(m => !newModelsMap.get(m.ko_url()));
|
||||
|
||||
// add models to the observable array, which are new in the
|
||||
// updated list
|
||||
for ( let idx in models) {
|
||||
let model = models[idx];
|
||||
if (!isModelInArray(observableModelsArray(), model)) {
|
||||
var modelsMap = new Map(observableModelsArray().map(m => [m.ko_url(), m]));
|
||||
|
||||
for (let model of models) {
|
||||
const m = modelsMap.get(model.url);
|
||||
|
||||
if (!m) {
|
||||
// add models to the observable array, which are new in the updated list
|
||||
model.ko_name = ko.observable(model.name);
|
||||
model.ko_url = ko.observable(model.url);
|
||||
model.ko_online = ko.observable(false);
|
||||
|
@ -71,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) {
|
||||
|
@ -83,31 +81,30 @@ function syncModels(models) {
|
|||
}
|
||||
});
|
||||
observableModelsArray.push(model);
|
||||
}
|
||||
}
|
||||
|
||||
// update existing models
|
||||
for ( let i in models) {
|
||||
let model = models[i];
|
||||
for ( let j in observableModelsArray()) {
|
||||
let m = observableModelsArray()[j];
|
||||
if (model.url === m.ko_url()) {
|
||||
m.ko_name(model.name);
|
||||
m.ko_url(model.url);
|
||||
let onlineState = false;
|
||||
for ( let i in onlineModels) {
|
||||
let onlineModel = onlineModels[i];
|
||||
if (onlineModel.url === model.url) {
|
||||
onlineState = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// update existing models
|
||||
m.ko_name(model.name);
|
||||
m.ko_url(model.url);
|
||||
let onlineState = false;
|
||||
for ( let i in onlineModels) {
|
||||
let onlineModel = onlineModels[i];
|
||||
if (onlineModel.url === model.url) {
|
||||
onlineState = true;
|
||||
break;
|
||||
}
|
||||
m.ko_online(onlineState);
|
||||
//m.ko_recording_class( (model.online && !model.suspended) ? 'fa fa-circle red' : '');
|
||||
m.swallowEvents = true;
|
||||
m.ko_suspended(model.suspended);
|
||||
m.swallowEvents = false;
|
||||
m.ko_recording(m.ko_online() && !m.ko_suspended());
|
||||
}
|
||||
m.ko_online(onlineState);
|
||||
//m.ko_recording_class( (model.online && !model.suspended) ? 'fa fa-circle red' : '');
|
||||
m.swallowEvents = true;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue