experimental wtv-search and wtv-proxy (disabled by default, requires external services)
This commit is contained in:
35
zefie_wtvp_minisrv/includes/ServiceDeps/https/zefienetCA.pem
Normal file
35
zefie_wtvp_minisrv/includes/ServiceDeps/https/zefienetCA.pem
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGJzCCBA+gAwIBAgIUTKPx4tUyiX93N/egPKsjfZQNlCUwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwgaExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwG
|
||||||
|
SHVkc29uMRcwFQYDVQQKDA5aZWZpZSBOZXR3b3JrczEZMBcGA1UECwwQTG9jYWwg
|
||||||
|
TmV0d29yayBDQTEaMBgGA1UEAwwRWmVmaWUgTmV0d29ya3MgQ0ExHjAcBgkqhkiG
|
||||||
|
9w0BCQEWD3plZmllQHplZmllLm5ldDAgFw0yNDEwMTkxNDIzNTdaGA8yMDg0MTAx
|
||||||
|
OTE0MjM1N1owgaExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhOZXcgWW9yazEPMA0G
|
||||||
|
A1UEBwwGSHVkc29uMRcwFQYDVQQKDA5aZWZpZSBOZXR3b3JrczEZMBcGA1UECwwQ
|
||||||
|
TG9jYWwgTmV0d29yayBDQTEaMBgGA1UEAwwRWmVmaWUgTmV0d29ya3MgQ0ExHjAc
|
||||||
|
BgkqhkiG9w0BCQEWD3plZmllQHplZmllLm5ldDCCAiIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggIPADCCAgoCggIBAJxwTr8iA/6kHZ3LL+PUQcAPqk9iRMH5YV4e1Wkq33cefFHN
|
||||||
|
8s/yqac1is48NJq2G3oEXnQo6e1Bo7Y3NfR4hAHzW7gz/lRxukKkI1XH6QyIVigd
|
||||||
|
sdRbq13WeDba2YEbJDP1XbbJMFupeZzEhOeG5EMRaqEgl0TE/AjOt2fD1iybA6Dr
|
||||||
|
z+wMA4LOFbfth0tfOpeioiDAVqkvhp9hl3UF5ThMBplQJ7k3KbX82jwc3Ihl4cla
|
||||||
|
bT7F+ypKieQx7YRl1JcqZ361TgbIzE/rEG7zK3bH9SJTjtqmphn9/3yZ8ualguqY
|
||||||
|
VkJz0fdOWPQaqLmR+hQaVlyEfUEEw89MZ/TPHZY8pW79fp7OrM/KEL6mEz8E1zmJ
|
||||||
|
T6n5+rILA3PM036qn1WEVvmh3Rtv5sINkrg7nNw6vZlDq8lzzu0cae+IqiikkTT+
|
||||||
|
oFZ40jFEdd1Cr0m1irU5rLaP/SpDK6uz1T+JWgDSS8vdIARzxMTrNnL0XnEmjVmn
|
||||||
|
kMab43iQ8UOcOmf/AJAdfzFS6C3SXLsz4aeeMKoEoFlut/8hWD3x6x9CTYUna18U
|
||||||
|
e5y3Lhe17yASxKCvGHjQ1WvV/FG5MYPosLwTq5Baq57DTrz1rR0oGqjTP5u9ehWg
|
||||||
|
8+3BbyU3kKEslsNlYsMAzRbqLe430WOBsgcJVMdUKmH7h3FfxmR+jsLrnJCXAgMB
|
||||||
|
AAGjUzBRMB0GA1UdDgQWBBSWZoNRxAe1AyZeCSu6xOsIIZmiyTAfBgNVHSMEGDAW
|
||||||
|
gBSWZoNRxAe1AyZeCSu6xOsIIZmiyTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
|
||||||
|
DQEBCwUAA4ICAQB7ek8RNQjcf9YlPPrMXsDHomSilDcEcjFZf6614SRjU+5WUgR0
|
||||||
|
ABtCBp2X4hZzFq6/Tp/B/Y5Lwcv0jn8EhvZ0eTPQ0hALAvVKUvAh1ZTiQKCNPqTn
|
||||||
|
xIJmeBKyWSfZUTOGiXoJnyi32wyIiKOLyqNWSFkR8GYIIhqQMTuGnMaXJ+XH2aJH
|
||||||
|
cNH0iXtl1I/BrVtYPGC5LEEiPVL3tgKPL9EXZik+SkP33IxPFX3DefjfDcsFPEAR
|
||||||
|
3T4026CTapMNKO3b6oQI8eeh91rLd2gzczdxjjod1W66xiNEdyFkHwxou236ePxV
|
||||||
|
wUTB6tLYFzT1y2S+ANTbDyJwXnJqm90cO5iwanyofThvStIOSS2WQFuFshpSE7DS
|
||||||
|
yCyc/z5T2/cM3DTTPJRQvOZHhJQdsS4Za4x/z9y3qi33Ko/L4YKCse49NqGG1BVm
|
||||||
|
SXajYj62koVmD5ZwvEISRWQaRCRHLAAU3kBZdC4edYmULf4R9ORg2Qe6oAsjoBJg
|
||||||
|
Sl4rmcM+0/ijviB8lARHNDwsxTUp6uhbe9pPKIH0dFN0G2JIe9tNHX8vpxIL+o9Q
|
||||||
|
iQRaJWl7eMMfewr7IDfQaajNRjK4XyBsV8NEZn0C/jaq92XNwRjjCDaJul40qbom
|
||||||
|
bv14SzRZP4arnRlCbfxxGlKfVoMf6rwlxmn5Jf5ArG+wm/+FGzdzcVlDQw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
minisrv_service_file = true;
|
||||||
|
request_is_async = true;
|
||||||
|
|
||||||
|
const proxyUrl = minisrv_config.services['wtv-proxy'].wrp_url;
|
||||||
|
if (!proxyUrl.endsWith('/')) {
|
||||||
|
proxyUrl += '/';
|
||||||
|
}
|
||||||
|
// Remove 'wtv-proxy:/' from the start of request_url
|
||||||
|
let forwardPath = request_headers.request_url.replace(/^wtv-proxy:\//, '');
|
||||||
|
|
||||||
|
// Build the full URL to forward to
|
||||||
|
const targetUrl = proxyUrl + forwardPath;
|
||||||
|
|
||||||
|
// Forward the request using http(s) module
|
||||||
|
const urlObj = new URL(targetUrl);
|
||||||
|
const lib = urlObj.protocol === 'https:' ? https : http;
|
||||||
|
|
||||||
|
lib.get(targetUrl, (res) => {
|
||||||
|
let headers = `200 OK\n`;
|
||||||
|
// Copy content-type if present
|
||||||
|
if (res.headers['content-type']) {
|
||||||
|
headers += `Content-Type: ${res.headers['content-type']}\n`;
|
||||||
|
}
|
||||||
|
// Optionally copy other headers as needed
|
||||||
|
|
||||||
|
let data = [];
|
||||||
|
res.on('data', chunk => data.push(chunk));
|
||||||
|
res.on('end', () => {
|
||||||
|
sendToClient(socket, headers, Buffer.concat(data));
|
||||||
|
});
|
||||||
|
}).on('error', err => {
|
||||||
|
sendToClient(socket, '200 OK\nContent-Type: text/plain', `Error fetching image: ${err.message}`);
|
||||||
|
});
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
minisrv_service_file = true;
|
||||||
|
request_is_async = true;
|
||||||
|
|
||||||
|
const proxyUrl = minisrv_config.services['wtv-proxy'].wrp_url;
|
||||||
|
if (!proxyUrl.endsWith('/')) {
|
||||||
|
proxyUrl += '/';
|
||||||
|
}
|
||||||
|
// Remove 'wtv-proxy:/' from the start of request_url
|
||||||
|
let forwardPath = request_headers.request_url.replace(/^wtv-proxy:\//, '');
|
||||||
|
|
||||||
|
// Build the full URL to forward to
|
||||||
|
var targetUrl = proxyUrl + forwardPath;
|
||||||
|
|
||||||
|
// Forward the request using http(s) module
|
||||||
|
const urlObj = new URL(targetUrl);
|
||||||
|
const lib = urlObj.protocol === 'https:' ? https : http;
|
||||||
|
|
||||||
|
coords = request_headers.request_url.split("?")[1];
|
||||||
|
if (!coords) {
|
||||||
|
coords = '0,0'
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Forwarding request to ${targetUrl} with coordinates ${coords}`);
|
||||||
|
targetUrl += `?${coords}`; // Append coordinates to the target URL
|
||||||
|
|
||||||
|
lib.get(targetUrl, (res) => {
|
||||||
|
let headers = `200 OK\n`;
|
||||||
|
// Copy content-type if present
|
||||||
|
if (res.headers['content-type']) {
|
||||||
|
headers += `Content-Type: ${res.headers['content-type']}\n`;
|
||||||
|
}
|
||||||
|
// Optionally copy other headers as needed
|
||||||
|
|
||||||
|
let data = '';
|
||||||
|
res.on('data', chunk => data += chunk);
|
||||||
|
res.on('end', () => {
|
||||||
|
if (data.startsWith('<HTML')) {
|
||||||
|
// success page
|
||||||
|
// Find all <a href="..."><img src="..."></a> and extract the URLs
|
||||||
|
const aHrefMatch = data.match(/<a\s+href="([^"]+)"/i);
|
||||||
|
const imgSrcMatch = data.match(/<img\s+src="([^"]+)"/i);
|
||||||
|
const links = [];
|
||||||
|
if (aHrefMatch && imgSrcMatch) {
|
||||||
|
links.push({
|
||||||
|
href: aHrefMatch[1],
|
||||||
|
img: imgSrcMatch[1]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var proxy_id = links[0].href.replace(/\/map\//, '');
|
||||||
|
proxy_id = proxy_id.replace(/\.map/, '');
|
||||||
|
var imgExt = links[0].img.split('.').pop().split('?')[0].toLowerCase();
|
||||||
|
const urlInputMatch = data.match(/<input[^>]+type=["']text["'][^>]+name=["']url["'][^>]+value=["']([^"']+)["']/i);
|
||||||
|
let pageUrl = '';
|
||||||
|
if (urlInputMatch) {
|
||||||
|
pageUrl = urlInputMatch[1];
|
||||||
|
}
|
||||||
|
var redirectUrl = `wtv-proxy:/proxy?id=${proxy_id}&t=${imgExt}&url=${encodeURIComponent(pageUrl)}`;
|
||||||
|
sendToClient(socket, {'Status': 302, 'Location': redirectUrl}, '');
|
||||||
|
} else {
|
||||||
|
var idx = data.indexOf('<BR>');
|
||||||
|
data = data.substring(0, idx);
|
||||||
|
var redirectUrl = `wtv-proxy:/proxy?err=${escape(data)}`;
|
||||||
|
sendToClient(socket, {'Status': 302, 'Location': redirectUrl}, '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).on('error', err => {
|
||||||
|
sendToClient(socket, '200 OK\nContent-Type: text/plain', `Error fetching image: ${err.message}`);
|
||||||
|
});
|
||||||
118
zefie_wtvp_minisrv/includes/ServiceVault/wtv-proxy/proxy.js
Normal file
118
zefie_wtvp_minisrv/includes/ServiceVault/wtv-proxy/proxy.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
minisrv_service_file = true;
|
||||||
|
request_is_async = true;
|
||||||
|
|
||||||
|
proxyUrl = minisrv_config.services[service_name].wrp_url;
|
||||||
|
if (!proxyUrl.endsWith('/')) {
|
||||||
|
proxyUrl += '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request_headers.query.url) {
|
||||||
|
headers = `200 OK
|
||||||
|
Content-Type: text/html`;
|
||||||
|
data = `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Web Rendering Proxy</title>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#191919" text="#44cc55" link="36d5ff" vlink="36d5ff">
|
||||||
|
<h1>Web Rendering Proxy</h1>
|
||||||
|
<p>Welcome to the Web Rendering Proxy.<br>Please provide a valid URL to render.</p>
|
||||||
|
<form method="POST" action="wtv-proxy:/proxy">
|
||||||
|
<label for="url"> URL:</label>
|
||||||
|
<input type="text" id="url" name="url" value="https://" size=38>
|
||||||
|
<input type="hidden" name="z" value="1.0">
|
||||||
|
<input type="hidden" name="t" value="jpg">
|
||||||
|
<input type="hidden" name="c" value="256">
|
||||||
|
<input type="hidden" name="m" value="ismap">
|
||||||
|
<input type="submit" value="Go">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>`
|
||||||
|
sendToClient(socket, headers, data);
|
||||||
|
} else {
|
||||||
|
if (request_headers.query.err) {
|
||||||
|
finishPage(`<h1>Error</h1><p>${request_headers.query.err}</p>`).join('<br>');
|
||||||
|
} else {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
url: request_headers.query.url,
|
||||||
|
z: request_headers.query.z || '1.0',
|
||||||
|
t: request_headers.query.t || 'jpg',
|
||||||
|
c: request_headers.query.c || '256',
|
||||||
|
m: request_headers.query.m || 'ismap'
|
||||||
|
});
|
||||||
|
const fullUrl = proxyUrl + '?' + params.toString();
|
||||||
|
const urlObj = new URL(fullUrl);
|
||||||
|
const lib = urlObj.protocol === 'https:' ? https : http;
|
||||||
|
if (request_headers.query.id) {
|
||||||
|
finishPage(`<a href="/map/${request_headers.query.id}.map"><img src="/img/${request_headers.query.id}.${params.get('t')}" ISMAP></a>`);
|
||||||
|
} else {
|
||||||
|
function fetch(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
lib.get(url, (res) => {
|
||||||
|
let data = '';
|
||||||
|
res.on('data', chunk => data += chunk);
|
||||||
|
res.on('end', () => resolve({ text: () => Promise.resolve(data) }));
|
||||||
|
}).on('error', reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fetch(fullUrl)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(text => { process(text); })
|
||||||
|
.catch(err => { finishPage(`Error fetching page: ${err.message}`); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function process(content) {
|
||||||
|
if (content.startsWith('<HTML')) {
|
||||||
|
// success page
|
||||||
|
// Find all <a href="..."><img src="..."></a> and extract the URLs
|
||||||
|
const aHrefMatch = content.match(/<a\s+href="([^"]+)"/i);
|
||||||
|
const imgSrcMatch = content.match(/<img\s+src="([^"]+)"/i);
|
||||||
|
const links = [];
|
||||||
|
if (aHrefMatch && imgSrcMatch) {
|
||||||
|
links.push({
|
||||||
|
href: aHrefMatch[1],
|
||||||
|
img: imgSrcMatch[1]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finishPage(links.map(link => `<a href="${link.href}"><img src="${link.img}" ISMAP></a>`).join('<br>'));
|
||||||
|
// You can now use the `links` array as needed
|
||||||
|
|
||||||
|
} else {
|
||||||
|
var idx = content.indexOf('<BR>');
|
||||||
|
content = content.substring(0, idx);
|
||||||
|
finishPage(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishPage(content) {
|
||||||
|
headers = `200 OK
|
||||||
|
Content-Type: text/html`;
|
||||||
|
data = `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Web Rendering Proxy</title>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#191919" text="#44cc55" link="36d5ff" vlink="36d5ff">
|
||||||
|
<form method="POST" action="wtv-proxy:/proxy">
|
||||||
|
<label for="url">URL:</label>
|
||||||
|
<input type="text" id="url" name="url" value="${request_headers.query.url}" size=30>
|
||||||
|
<input type="hidden" name="z" value="${request_headers.query.z || '1.0'}">
|
||||||
|
<input type="hidden" name="t" value="${request_headers.query.t || 'jpg'}">
|
||||||
|
<input type="hidden" name="c" value="${request_headers.query.c || '216'}">
|
||||||
|
<input type="submit" value="Go">
|
||||||
|
<input type="submit" name="Fn" value="Bk">
|
||||||
|
<input type="submit" name="Fn" value="Re">
|
||||||
|
<hr>
|
||||||
|
${content}
|
||||||
|
</form>
|
||||||
|
<hr>
|
||||||
|
<center>
|
||||||
|
<a href="/proxy">Start Over</a>
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
sendToClient(socket, headers, data);
|
||||||
|
}
|
||||||
122
zefie_wtvp_minisrv/includes/ServiceVault/wtv-search/search.js
Normal file
122
zefie_wtvp_minisrv/includes/ServiceVault/wtv-search/search.js
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
minisrv_service_file = true;
|
||||||
|
request_is_async = true;
|
||||||
|
|
||||||
|
var searchUrl = minisrv_config.services[service_name].searxng_url;
|
||||||
|
if (!searchUrl.endsWith('/')) {
|
||||||
|
searchUrl += '/';
|
||||||
|
}
|
||||||
|
searchUrl += 'search';
|
||||||
|
|
||||||
|
if (!request_headers.query.q) {
|
||||||
|
const headers = `200 OK\nContent-Type: text/html`;
|
||||||
|
const data = `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Web Search Proxy</title>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#191919" text="#44cc55" link="36d5ff" vlink="36d5ff">
|
||||||
|
<h1>WebTV Search</h1>
|
||||||
|
<p>Please provide a search query.</p>
|
||||||
|
<form method="POST" action="wtv-search:/search">
|
||||||
|
<label for="q"> Query:</label>
|
||||||
|
<input type="text" id="q" name="q" value="" size=30>
|
||||||
|
<input type="hidden" name="safesearch" value="0">
|
||||||
|
<input type="hidden" name="language" value="auto">
|
||||||
|
<input type="hidden" name="time_range" value="">
|
||||||
|
<select name="categories">
|
||||||
|
<option value="general">General</option>
|
||||||
|
<option value="images">Images</option>
|
||||||
|
</select>
|
||||||
|
<input type="submit" value="Search">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
sendToClient(socket, headers, data);
|
||||||
|
} else {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
for (const key in request_headers.query) {
|
||||||
|
if (request_headers.query.hasOwnProperty(key)) {
|
||||||
|
params.append(key, request_headers.query[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params.append('format', 'json');
|
||||||
|
const urlObj = new URL(searchUrl);
|
||||||
|
const lib = urlObj.protocol === 'https:' ? https : http;
|
||||||
|
var post_data = params.toString();
|
||||||
|
const options = {
|
||||||
|
protocol: urlObj.protocol,
|
||||||
|
hostname: urlObj.hostname,
|
||||||
|
port: parseInt(urlObj.port) || (urlObj.protocol === 'https:' ? 443 : 80),
|
||||||
|
path: urlObj.pathname + (urlObj.search || ''),
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'User-Agent': request_headers['User-Agent'] || 'Mozilla/4.0 WebTV/2.6 (compatible; MSIE 4.0)',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'Content-Length': Buffer.byteLength(post_data),
|
||||||
|
'Accept': 'application/json, text/plain, */*',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (urlObj.protocol === 'https:' && urlObj.hostname.includes("lan.zef")) {
|
||||||
|
options.ca = wtvshared.getServiceDep('https/zefienetCA.pem');
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(lib, options, post_data)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(text => { process(text); })
|
||||||
|
.catch(err => { finishPage(`Error fetching page: ${err.message}`); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetch(lib, options, post_data) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var req = lib.request(options, (res) => {
|
||||||
|
let data = '';
|
||||||
|
res.on('data', chunk => data += chunk);
|
||||||
|
res.on('end', () => resolve({ text: () => Promise.resolve(data) }));
|
||||||
|
}).on('error', reject);
|
||||||
|
req.write(post_data); // 🔁 Send body
|
||||||
|
req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function process(data) {
|
||||||
|
if (data === "Too Many Requests") {
|
||||||
|
sendToClient(socket, '400 SearXNG reported<br>"Too Many Requests"<br><br>Please check your limiter.toml.\nContent-Type: text/plain', 'SearXNG reported "Too Many Requests", please check your limiter.toml');
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const results = JSON.parse(data).results || [];
|
||||||
|
let content = '';
|
||||||
|
if (results.length === 0) {
|
||||||
|
content = '<h1>No results found</h1>';
|
||||||
|
} else {
|
||||||
|
content = '<h1>Search Results</h1>';
|
||||||
|
results.forEach(result => {
|
||||||
|
content += `<p><a href="${result.url}" target="_blank">${result.title}</a><br>${result.content || `<img src="${result.thumbnail_src}">` || ''}</p><br>`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finishPage(content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishPage(content) {
|
||||||
|
const headers = `200 OK\nContent-Type: text/html`;
|
||||||
|
const data = `
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Web Search Proxy</title>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#191919" text="#44cc55" link="36d5ff" vlink="36d5ff">
|
||||||
|
<form method="POST" action="wtv-search:/search">
|
||||||
|
<label for="q">Query:</label>
|
||||||
|
<input type="text" id="q" name="q" value="${request_headers.query.q}" size=30>
|
||||||
|
<select name="categories">
|
||||||
|
<option value="general" ${request_headers.query.categories === 'general' ? 'selected' : ''}>General</option>
|
||||||
|
<option value="images" ${request_headers.query.categories === 'images' ? 'selected' : ''}>Images</option>
|
||||||
|
</select>
|
||||||
|
<input type="submit" value="Search">
|
||||||
|
</form>
|
||||||
|
${content}
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
sendToClient(socket, headers, data);
|
||||||
|
}
|
||||||
@@ -393,6 +393,16 @@
|
|||||||
"connections": 3,
|
"connections": 3,
|
||||||
"flags": "0x00000004"
|
"flags": "0x00000004"
|
||||||
},
|
},
|
||||||
|
"wtv-search": {
|
||||||
|
"disabled": true,
|
||||||
|
"port": 1695,
|
||||||
|
"searxng_url": "http://192.168.11.20:9999/" // replace with your own searxng instance
|
||||||
|
},
|
||||||
|
"wtv-proxy": {
|
||||||
|
"disabled": true,
|
||||||
|
"port": 1696,
|
||||||
|
"wrp_url": "http://192.168.11.20:8889/" // replace with your own tenox9/wrp
|
||||||
|
},
|
||||||
"pb_services": {
|
"pb_services": {
|
||||||
// PC Services for PageBuilder
|
// PC Services for PageBuilder
|
||||||
"port": 1697,
|
"port": 1697,
|
||||||
|
|||||||
Reference in New Issue
Block a user