You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
6.3 KiB
182 lines
6.3 KiB
const fs = require("fs");
|
|
const http = require("http");
|
|
const https = require("https");
|
|
const path = require("path");
|
|
const {execSync} = require('child_process');
|
|
const express = require("express"); // could be good to replace with code, no dep
|
|
|
|
// Get port or default to 8082
|
|
const port = process.env.PORT || 8082;
|
|
|
|
// Setup and configure Express http server.
|
|
const app = express();
|
|
app.use(express.static(path.resolve(__dirname, ".", "examples")));
|
|
|
|
const instructions = `
|
|
/home/deck/.ssh/
|
|
trusted context, i.e on closed WiFi and over https, still. could check as bearer
|
|
/home/deck/.ssh/config
|
|
could limit to known IP range or class e.g cat .ssh/config | grep 192.168.4. -C 3
|
|
could also re-add new entries rather than extend the format
|
|
/home/deck/.ssh/authorized_keys
|
|
/home/deck/.ssh/known_hosts
|
|
/home/deck/.ssh/id_rsa_steamdeck
|
|
/home/deck/.ssh/id_rsa_steamdeck.pub
|
|
|
|
/home/deck/server.locatedb
|
|
seems to be plain text with metadata
|
|
/home/deck/desktop.plocate.db
|
|
seems to be a specific format, binary or maybe compressed
|
|
both should be queriable via http with json output
|
|
|
|
ssh remarkable2 to get drawing preview
|
|
conversion should be done, if necessary, on device
|
|
for typed text
|
|
cat 43*.rm | sed "s/[^a-zA-z0-9 ]//g" | sed "s/[OT,EC]//g"
|
|
|
|
util functions
|
|
modify WiFi parameters, including AP if available
|
|
shutdown/reboot
|
|
`
|
|
app.get('/pwa', (req, res) => {
|
|
// for offline use on mobile or VR headset
|
|
// should try to sync back when devices connect back
|
|
// same when itself connects back to (Internet) own server e.g benetou.fr
|
|
// can be cascading or federatede or properly P2P
|
|
// responsive programming also, not "just" design
|
|
res.redirect('pwa/index.html')
|
|
})
|
|
const utilsCmd = {
|
|
'shutdown' : { cmd: 'shutdown -h now' },
|
|
'listprototypes': { cmd: 'ls', context: {cwd: '/home/deck/Prototypes'},
|
|
// more reliably path.join(__dirname,'')
|
|
format: res => res.toString().split('\n')
|
|
},
|
|
}
|
|
app.get('/exec', (req, res) => {
|
|
if (!req.query.cmdName){
|
|
res.json(utilsCmd)
|
|
} else {
|
|
|
|
let resultFromExecution = execSync(utilsCmd[req.query.cmdName].cmd, utilsCmd[req.query.cmdName].context)
|
|
let formatter = utilsCmd[req.query.cmdName].format
|
|
if (formatter) resultFromExecution = formatter(resultFromExecution)
|
|
res.json( resultFromExecution )
|
|
}
|
|
})
|
|
// app.get('/interface/unregister', (req, res) => {
|
|
// app.get('/interface/register', (req, res) => {
|
|
// could be use for e.g reMarkable2, Quest2, etc with specifically accepted or prefered formats
|
|
app.get('/services/unregister', (req, res) => {
|
|
res.json( {msg: 'not yet implemented'})
|
|
})
|
|
app.get('/services/register', (req, res) => {
|
|
res.json( {msg: 'not yet implemented'})
|
|
// example {name:'hmdlink', desc:'share URL between local devices', protocol:'http', port:8082, path: '/hmdlink', url:'http://192.168.4.3:8082/hmdlink'},
|
|
})
|
|
app.get('/services', (req, res) => {
|
|
// could be probbed first to check for availability
|
|
// should be updated also via register/unregister
|
|
res.json( [
|
|
{name:'kiwix', desc:'offline Wikipedia, Stackoverflow, etc', protocol:'http', port:8080, url:'http://192.168.4.3:8080'},
|
|
{name:'hmdlink', desc:'share URL between local devices', protocol:'http', port:8082, path: '/hmdlink', url:'http://192.168.4.3:8082/hmdlink'},
|
|
|
|
] )
|
|
})
|
|
|
|
let dynURL = 'https://192.168.4.1/offline.html'
|
|
app.get('/hmdlink/set', (req, res) => { // could be a PUT instead
|
|
// e.g http://192.168.4.3:8082/hmdlink/set?url=http://192.168.4.3:8082/114df5f8-3921-42f0-81e7-48731b563571.thumbnails/f07120ba-0ca1-429d-869f-c704a52b7aa3.png
|
|
dynURL = req.query.url
|
|
res.redirect( dynURL )
|
|
})
|
|
app.get('/webxr', (req, res) => {
|
|
res.redirect( '/local-metaverse-tooling/local-aframe-test.html' )
|
|
})
|
|
app.get('/hmdlink', (req, res) => {
|
|
res.redirect( dynURL )
|
|
})
|
|
app.get('/json', (req, res) => {
|
|
res.json( instructions.split('\n') )
|
|
})
|
|
app.get('/available', (req, res) => {
|
|
res.json( true )
|
|
})
|
|
app.get('/foundpeers', (req, res) => {
|
|
res.json( foundPeers )
|
|
})
|
|
let foundPeers = []
|
|
app.get('/scan', (req, res) => {
|
|
for (let i=1;i<25;i++){ // async so blasting, gives very quick result for positives
|
|
let url='https://192.168.4.'+i+':8082/available'
|
|
let opt={rejectUnauthorized: false}
|
|
https.get(url, opt, res => {
|
|
let data = '';
|
|
res.on('data', chunk => {
|
|
data += chunk;
|
|
});
|
|
res.on('end', () => {
|
|
data = JSON.parse(data);
|
|
foundPeers.push(i)
|
|
// could also register there and then
|
|
})
|
|
}).on('error', err => {
|
|
//console.log(err.message); usually ECONNREFUSED or EHOSTUNREACH
|
|
}).end()
|
|
}
|
|
res.json( {msg: 'started'} ) // could redirect('/foundpeers') too
|
|
})
|
|
app.get('/', (req, res) => {
|
|
res.send( instructions )
|
|
})
|
|
app.get('/localprototypes', (req, res) => {
|
|
// res.json( spawn('find Prototypes/ -iwholename */.git/config | xargs grep git.benetou.fr') )
|
|
// should use execSync now
|
|
})
|
|
app.get('/editor/recover', (req, res) => {
|
|
// could move the previous file with time stamp
|
|
fs.copyFileSync(minfileSaveFullPath, fileSaveFullPath )
|
|
res.json( {msg: 'copied'} )
|
|
})
|
|
let filename = 'editor.html'
|
|
let fileSaveFullPath = path.join(__dirname,'examples', filename)
|
|
let minfilename = 'editor.html.minimal'
|
|
let minfileSaveFullPath = path.join(__dirname,'examples', minfilename)
|
|
app.get('/editor/read', (req, res) => {
|
|
content = fs.readFileSync(fileSaveFullPath ).toString()
|
|
res.json( {msg: content} )
|
|
})
|
|
app.get('/editor/save', (req, res) => {
|
|
let content = req.query.content // does not escape, loses newlines
|
|
if (!content){
|
|
res.json( {msg: 'missing content'} )
|
|
} else {
|
|
console.log('writting', content)
|
|
fs.writeFileSync(fileSaveFullPath, content)
|
|
res.json( {msg: 'written to '+fileSaveFullPath} )
|
|
}
|
|
})
|
|
|
|
const privateKey = fs.readFileSync("naf-key.pem", "utf8");
|
|
const certificate = fs.readFileSync("naf.pem", "utf8");
|
|
const credentials = { key: privateKey, cert: certificate };
|
|
|
|
const webServer = https.createServer(credentials, app);
|
|
// Start Express http server
|
|
// const webServer = http.createServer(app);
|
|
// Listen on port
|
|
webServer.listen(port, () => {
|
|
console.log("listening on http://localhost:" + port);
|
|
});
|
|
/*
|
|
e.g AFTER mounting
|
|
f.readdirSync('./sshfsmounts/').map( d=>f.readdirSync('./sshfsmounts/'+d) )
|
|
location : /home/deck/Prototypes/offline-octopus/sshfsmounts
|
|
sshfs remarkable2:/home/root/xochitl-data/ remarkable2/
|
|
works if available
|
|
sshfs fabien@192.168.4.1:/home/fabien/ rpi0/
|
|
still prompts for password, need manual login
|
|
ls rpi0/
|
|
ls remarkable2/
|
|
*/
|
|
|
|
|