Skip to content

Commit

Permalink
Final touches as described in the tutorial
Browse files Browse the repository at this point in the history
(Plus the addition of a public-domain favicon.)
  • Loading branch information
codingthat committed Apr 17, 2020
1 parent 6971519 commit 8713e84
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 30 deletions.
1 change: 1 addition & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
console.error(err.stack);

// render the error page
res.status(err.status || 500);
Expand Down
Binary file added public/favicon.ico
Binary file not shown.
30 changes: 29 additions & 1 deletion public/javascript/group-client.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
(function () {
var timers = {};
function form_submit(event) {
event.target.classList.remove('error');
event.target.classList.remove('success');
if (timers[event.target.value]) {
window.clearTimeout(timers[event.target.value]);
delete timers[event.target];
}
event.target.classList.add('loading');
var request = new XMLHttpRequest();
request.open('POST', window.location.pathname + window.location.search, true);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

request.onerror = function() {
event.target.classList.remove('loading');
event.target.classList.add('error');
timers[event.target.value] = window.setTimeout(function(){
event.target.classList.remove('error');
}, 5000);
};
request.onload = function() {
if (request.status !== 200) {
request.onerror();
return;
}
event.target.classList.remove('loading');
event.target.classList.add('success');
timers[event.target.value] = window.setTimeout(function(){
event.target.classList.remove('success');
}, 1000);
};

request.send('keystroke_name=' + encodeURIComponent(event.target.value));
event.preventDefault();
}
Expand All @@ -12,4 +40,4 @@
inputs[i].addEventListener("click", form_submit);
}
});
})();
})();
6 changes: 5 additions & 1 deletion public/stylesheets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ html, body, form {
width: calc(100%/3);
height: calc(100%/3);
font-size: 12vh;
}
}

.loading { border: 15px dashed grey; }
.success { border: 15px dashed greenyellow; }
.error { border: 15px dashed red; }
96 changes: 70 additions & 26 deletions routes/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,76 @@ const router = express.Router();
const cp = require('child_process');
const preset_commands = require('../common/preset_commands');

/* POST keystroke to simulate */
router.post('/', function(req, res, next) {

const keystroke_name = req.body.keystroke_name;
const keystroke_code = preset_commands['YouTube'].commands[keystroke_name];
const final_command = `xdotool \
search "YouTube" \
windowactivate --sync \
key --clearmodifiers ${keystroke_code}`;

console.log(`Executing ${final_command}`);
cp.exec(final_command, (err, stdout, stderr) => {
console.log(`Executed ${keystroke_name}`);
return res.redirect(req.originalUrl);
});
});

router.get('/', function(req, res, next) {
const group_name = req.query.group_name || '';
const check_group = (query, res) => {
const group_name = query.group_name || '';
if (!group_name) {
res.status(404).render('error', { error: 'No group specified', detail: `URL should end in ?group_name=(the escaped group name here)` });
return { check_group_error: true };
}
const group = preset_commands[group_name];
if (!group) {
res.status(404).render('error', { error: 'Group not found', detail: `Received name '${group_name}' but couldn't find it among presets` });
return { check_group_error: true };
}
if (!group.commands) {
res.status(404).render('error', { error: 'Group empty', detail: `Found group '${group_name}' but it has no commands defined` });
return { check_group_error: true };
}
return { group_name, group };
};

return res.render('group', {
keystroke_names: Object.keys(group.commands),
group_name,
title: `${group_name.match(/([A-Z])/g).join('')}-Remote`
});
});
router.route('/')

module.exports = router;
/* GET remote control layout for a particular group */
.get((req, res) => {
const { group_name, group, check_group_error } = check_group(req.query, res);
if (check_group_error) return;
res.render('group', {
keystroke_names: Object.keys(group.commands),
group_name,
title: `${group_name.match(/([A-Z])/g).join('')}-Remote`
});
})

/* POST keystroke to simulate */
.post((req, res) => {
const keystroke_name = req.body.keystroke_name || '';
if (keystroke_name === '') {
return res.status(400).render('error', { error: 'No key sent' });
}

const { group_name, group, check_group_error } = check_group(req.query, res);
if (check_group_error) return;
if (!group.commands[keystroke_name]) {
return res.status(400).render('error', { error: 'Key not allowed', detail: `Key not found in commands of group '${group_name}'` });
}

const window_name = (group.hasOwnProperty('window_name_override') // allow blanks
? group.window_name_override
: group_name).replace(/"/g, '\\"');

const window_search_and_activate = window_name
? `search "${window_name}" windowactivate --sync`
: '';

const final_command = `xdotool \
${window_search_and_activate} \
key --clearmodifiers ${group.commands[keystroke_name]}`;

console.log(`Executing ${final_command}`);
cp.exec(final_command, (err, stdout, stderr) => {
if (err) {
console.error(err);
return res.status(400).render('error', { error: 'Exec call failed', detail: err });
} else if (stderr.match('No such key name')) {
console.error(stderr);
return res.status(400).render('error', { error: 'Invalid keycode', detail: stderr });
} else {
console.log(`Executed ${keystroke_name}`);
return res.redirect(req.originalUrl);
}
});
})
;

module.exports = router;
4 changes: 2 additions & 2 deletions views/error.pug
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ extends layout

block content
h1= message
h2= error.status
pre #{error.stack}
h2= error
h3= detail

0 comments on commit 8713e84

Please sign in to comment.