Implement loading of the config into the webpage
This commit is contained in:
parent
1b75340f74
commit
44fd340323
|
@ -57,7 +57,7 @@ the port ctbrec tries to connect to, if it is run in remote mode.
|
||||||
|
|
||||||
- **recordSingleFile** (server only) - [`true`,`false`] - How recordings are stored in the file system. `true` means, each recording is saved in one large file. `false` means, ctbrec just downloads the stream segments.
|
- **recordSingleFile** (server only) - [`true`,`false`] - How recordings are stored in the file system. `true` means, each recording is saved in one large file. `false` means, ctbrec just downloads the stream segments.
|
||||||
|
|
||||||
- **splitRecordings** (app only) - [0 - 2147483647] in seconds. Split recordings after this amount of seconds. The recordings are split up into several individual recordings,
|
- **splitRecordings** - [0 - 2147483647] in seconds. Split recordings after this amount of seconds. The recordings are split up into several individual recordings,
|
||||||
which have the defined length (roughly). 0 means no splitting. The server does not support splitRecordings.
|
which have the defined length (roughly). 0 means no splitting. The server does not support splitRecordings.
|
||||||
|
|
||||||
- **webinterface** (server only) - [`true`,`false`] Enables the webinterface for the server. You can access it with http://host:port/static/index.html Don't activate this on
|
- **webinterface** (server only) - [`true`,`false`] Enables the webinterface for the server. You can access it with http://host:port/static/index.html Don't activate this on
|
||||||
|
|
|
@ -3,6 +3,8 @@ package ctbrec.recorder.server;
|
||||||
import static javax.servlet.http.HttpServletResponse.*;
|
import static javax.servlet.http.HttpServletResponse.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -36,26 +38,45 @@ public class ConfigServlet extends AbstractCtbrecServlet {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
// try {
|
try {
|
||||||
// boolean authenticated = checkAuthentication(req, body(req));
|
boolean authenticated = checkAuthentication(req, body(req));
|
||||||
// if (!authenticated) {
|
if (!authenticated) {
|
||||||
// resp.setStatus(SC_UNAUTHORIZED);
|
resp.setStatus(SC_UNAUTHORIZED);
|
||||||
// String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
|
String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
|
||||||
// resp.getWriter().write(response);
|
resp.getWriter().write(response);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
// } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
|
||||||
// throw new ServletException(e);
|
|
||||||
// }
|
|
||||||
|
|
||||||
resp.setStatus(SC_OK);
|
JSONArray json = new JSONArray();
|
||||||
resp.setContentType("application/json");
|
addParameter("concurrentRecordings", "Concurrent Recordings", DataType.INTEGER, settings.concurrentRecordings, json);
|
||||||
|
addParameter("ffmpegFileSuffix", "File Suffix", DataType.STRING, settings.ffmpegFileSuffix, json);
|
||||||
|
addParameter("ffmpegMergedDownloadArgs", "FFmpeg Parameters", DataType.STRING, settings.ffmpegMergedDownloadArgs, json);
|
||||||
|
addParameter("httpPort", "HTTP port", DataType.INTEGER, settings.httpPort, json);
|
||||||
|
addParameter("httpsPort", "HTTPS port", DataType.INTEGER, settings.httpSecurePort, json);
|
||||||
|
addParameter("httpUserAgent", "User-Agent", DataType.STRING, settings.httpUserAgent, json);
|
||||||
|
addParameter("httpUserAgentMobile", "Mobile User-Agent", DataType.STRING, settings.httpUserAgentMobile, json);
|
||||||
|
addParameter("generatePlaylist", "Generate Playlist", DataType.BOOLEAN, settings.generatePlaylist, json);
|
||||||
|
addParameter("maximumResolution", "Maximum Resolution", DataType.INTEGER, settings.maximumResolution, json);
|
||||||
|
addParameter("minimumLengthInSeconds", "Minimum Length (secs)", DataType.INTEGER, settings.minimumLengthInSeconds, json);
|
||||||
|
addParameter("minimumSpaceLeftInBytes", "Leave Space On Device (GiB)", DataType.INTEGER, settings.minimumSpaceLeftInBytes, json);
|
||||||
|
addParameter("onlineCheckIntervalInSecs", "Online Check Interval (secs)", DataType.INTEGER, settings.onlineCheckIntervalInSecs, json);
|
||||||
|
addParameter("postProcessing", "Post-Processing", DataType.STRING, settings.postProcessing, json);
|
||||||
|
addParameter("postProcessingThreads", "Post-Processing Threads", DataType.INTEGER, settings.postProcessingThreads, json);
|
||||||
|
addParameter("recordingsDir", "Recordings Directory", DataType.STRING, settings.recordingsDir, json);
|
||||||
|
addParameter("recordSingleFile", "Record Single File", DataType.BOOLEAN, settings.recordSingleFile, json);
|
||||||
|
addParameter("splitRecordings", "Split Recordings (secs)", DataType.INTEGER, settings.splitRecordings, json);
|
||||||
|
addParameter("transportLayerSecurity", "Transport Layer Security (TLS)", DataType.BOOLEAN, settings.transportLayerSecurity, json);
|
||||||
|
addParameter("webinterface", "Web-Interface", DataType.BOOLEAN, settings.webinterface, json);
|
||||||
|
addParameter("webinterfaceUsername", "Web-Interface User", DataType.STRING, settings.webinterfaceUsername, json);
|
||||||
|
addParameter("webinterfacePassword", "Web-Interface Password", DataType.STRING, settings.webinterfacePassword, json);
|
||||||
|
|
||||||
JSONArray json = new JSONArray();
|
resp.setStatus(SC_OK);
|
||||||
addParameter("httpPort", "HTTP port", DataType.INTEGER, settings.httpPort, json);
|
resp.setContentType("application/json");
|
||||||
|
resp.getWriter().print(json.toString());
|
||||||
resp.getWriter().print(json.toString(2));
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
||||||
LOG.debug("GET {} {}", req.getRequestURI(), req.getRequestURL());
|
resp.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||||
|
LOG.error("Error during authentication", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addParameter(String key, String name, DataType type, Object value, JSONArray json) {
|
private void addParameter(String key, String name, DataType type, Object value, JSONArray json) {
|
||||||
|
@ -69,8 +90,24 @@ public class ConfigServlet extends AbstractCtbrecServlet {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
resp.setStatus(SC_OK);
|
try {
|
||||||
resp.setContentType("application/json");
|
boolean authenticated = checkAuthentication(req, body(req));
|
||||||
LOG.debug("POST");
|
if (!authenticated) {
|
||||||
|
resp.setStatus(SC_UNAUTHORIZED);
|
||||||
|
String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
|
||||||
|
resp.getWriter().write(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String postBody = body(req);
|
||||||
|
LOG.info("POST {}", postBody);
|
||||||
|
//JSONObject json = new JSONObject(postBody);
|
||||||
|
resp.setStatus(SC_OK);
|
||||||
|
resp.setContentType("application/json");
|
||||||
|
resp.getWriter().print("{\"status\": \"success\"}");
|
||||||
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
||||||
|
resp.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,14 +211,16 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startByUrl(Request request) throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, IOException {
|
private void startByUrl(Request request) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
String url = request.model.getUrl();
|
String url = request.model.getUrl();
|
||||||
for (Site site : sites) {
|
for (Site site : sites) {
|
||||||
Model model = site.createModelFromUrl(url);
|
Model model = site.createModelFromUrl(url);
|
||||||
if (model != null) {
|
if (model != null) {
|
||||||
recorder.startRecording(model);
|
recorder.startRecording(model);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException("No site found to record " + url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Request {
|
private static class Request {
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
function loadConfig() {
|
||||||
|
try {
|
||||||
|
$.ajax({
|
||||||
|
type : 'GET',
|
||||||
|
url : '../config',
|
||||||
|
dataType : 'json',
|
||||||
|
async : true,
|
||||||
|
timeout : 60000,
|
||||||
|
headers : {
|
||||||
|
'CTBREC-HMAC' : CryptoJS.HmacSHA256('', hmac)
|
||||||
|
}
|
||||||
|
}).done(function(data, textStatus, jqXHR) {
|
||||||
|
if (textStatus === 'success') {
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let param = data[i];
|
||||||
|
param.ko_value = ko.observable(param.value);
|
||||||
|
param.ko_value.subscribe(function(newValue) {
|
||||||
|
console.log("The person's new name is " + newValue);
|
||||||
|
});
|
||||||
|
observableSettingsArray.push(param);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (console)
|
||||||
|
console.log('request failed', data);
|
||||||
|
}
|
||||||
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||||
|
if (console)
|
||||||
|
console.log(jqXHR, textStatus, errorThrown);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
if (console)
|
||||||
|
console.log('Unexpected error', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveConfig() {
|
||||||
|
try {
|
||||||
|
let msg = JSON.stringify(observableSettingsArray());
|
||||||
|
console.log(msg);
|
||||||
|
$.ajax({
|
||||||
|
type : 'POST',
|
||||||
|
url : '../config',
|
||||||
|
dataType : 'json',
|
||||||
|
async : true,
|
||||||
|
timeout : 60000,
|
||||||
|
headers : {
|
||||||
|
'CTBREC-HMAC' : CryptoJS.HmacSHA256(msg, hmac)
|
||||||
|
},
|
||||||
|
data : msg
|
||||||
|
}).done(function(data, textStatus, jqXHR) {
|
||||||
|
if (textStatus === 'success') {
|
||||||
|
//$.notify('Configuration saved', 'info');
|
||||||
|
} else {
|
||||||
|
if (console)
|
||||||
|
console.log('request failed', data);
|
||||||
|
}
|
||||||
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||||
|
if (console)
|
||||||
|
console.log(jqXHR, textStatus, errorThrown);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
if (console)
|
||||||
|
console.log('Unexpected error', e);
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,9 +66,9 @@
|
||||||
<li class="nav-item mx-0 mx-lg-1"><a id="models-tab" data-toggle="tab" class="nav-link py-3 px-0 px-lg-3 rounded active" href="#models" role="tab"
|
<li class="nav-item mx-0 mx-lg-1"><a id="models-tab" data-toggle="tab" class="nav-link py-3 px-0 px-lg-3 rounded active" href="#models" role="tab"
|
||||||
aria-controls="models" aria-selected="true">Models</a></li>
|
aria-controls="models" aria-selected="true">Models</a></li>
|
||||||
<li class="nav-item mx-0 mx-lg-1"><a id="recordings-tab" data-toggle="tab" class="nav-link py-3 px-0 px-lg-3 rounded" href="#recordings" role="tab"
|
<li class="nav-item mx-0 mx-lg-1"><a id="recordings-tab" data-toggle="tab" class="nav-link py-3 px-0 px-lg-3 rounded" href="#recordings" role="tab"
|
||||||
aria-controls="profile" aria-selected="false">Recordings</a></li>
|
aria-controls="recordings" aria-selected="false">Recordings</a></li>
|
||||||
<li class="nav-item mx-0 mx-lg-1"><a id="configuration-tab" data-toggle="tab" class="nav-link py-3 px-0 px-lg-3 rounded" href="#configuration" role="tab"
|
<li class="nav-item mx-0 mx-lg-1"><a id="configuration-tab" data-toggle="tab" class="nav-link py-3 px-0 px-lg-3 rounded" href="#configuration" role="tab"
|
||||||
aria-controls="profile" aria-selected="false">Settings</a></li>
|
aria-controls="settings" aria-selected="false">Settings</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -174,11 +174,34 @@
|
||||||
</section>
|
</section>
|
||||||
<section id="configuration" class="tab-pane fade" role="tabpanel" aria-labelledby="configuration-tab">
|
<section id="configuration" class="tab-pane fade" role="tabpanel" aria-labelledby="configuration-tab">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<form data-bind="submit: saveConfig">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-10 mx-auto">
|
<div class="col-lg-10 mx-auto">
|
||||||
<h3>Not implemented, yet!</h3>
|
<p class="lead"></p>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-hover table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody data-bind="foreach: settings">
|
||||||
|
<tr>
|
||||||
|
<td data-bind="text: name"></td>
|
||||||
|
<td><input data-bind="value: value" style="width: 100%"/></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-10 mx-auto">
|
||||||
|
<button type="submit" class="btn btn-primary btn-lg btn-block" style="margin-bottom: 2em">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
@ -218,10 +241,12 @@
|
||||||
<!-- ctbrec stuff -->
|
<!-- ctbrec stuff -->
|
||||||
<script src="recordings.js"></script>
|
<script src="recordings.js"></script>
|
||||||
<script src="models.js"></script>
|
<script src="models.js"></script>
|
||||||
|
<script src="config.js"></script>
|
||||||
<script>
|
<script>
|
||||||
let onlineModels = [];
|
let onlineModels = [];
|
||||||
let observableModelsArray = ko.observableArray();
|
let observableModelsArray = ko.observableArray();
|
||||||
let observableRecordingsArray = ko.observableArray();
|
let observableRecordingsArray = ko.observableArray();
|
||||||
|
let observableSettingsArray = ko.observableArray();
|
||||||
let space = {
|
let space = {
|
||||||
free: ko.observable(0),
|
free: ko.observable(0),
|
||||||
total: ko.observable(0),
|
total: ko.observable(0),
|
||||||
|
@ -432,11 +457,19 @@
|
||||||
ko.applyBindings({
|
ko.applyBindings({
|
||||||
models : observableModelsArray,
|
models : observableModelsArray,
|
||||||
recordings: observableRecordingsArray,
|
recordings: observableRecordingsArray,
|
||||||
|
settings: observableSettingsArray,
|
||||||
space
|
space
|
||||||
});
|
});
|
||||||
|
|
||||||
updateOnlineModels();
|
updateOnlineModels();
|
||||||
updateRecordings();
|
updateRecordings();
|
||||||
|
|
||||||
|
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||||
|
let selectedTab = e.target.attributes['id'].value;
|
||||||
|
if (selectedTab === 'configuration-tab') {
|
||||||
|
loadConfig();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue