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.
 
 
offline-octopus/index.js

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/
*/