feat: mac-agent with AppleScript dispatch and unit tests
parent
ac19753ace
commit
c470d28f59
|
|
@ -0,0 +1,49 @@
|
||||||
|
const { resolveCommand } = require('../electron/mac-agent');
|
||||||
|
|
||||||
|
describe('resolveCommand', () => {
|
||||||
|
test('bekannter Shortcut → applescript', () => {
|
||||||
|
expect(resolveCommand('spotify_play')).toEqual({
|
||||||
|
type: 'applescript',
|
||||||
|
script: 'tell application "Spotify" to play',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('script: Präfix → applescript mit direktem Script', () => {
|
||||||
|
expect(resolveCommand('script:tell application "Finder" to activate')).toEqual({
|
||||||
|
type: 'applescript',
|
||||||
|
script: 'tell application "Finder" to activate',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('open: Präfix → URL öffnen', () => {
|
||||||
|
expect(resolveCommand('open:https://example.com')).toEqual({
|
||||||
|
type: 'open',
|
||||||
|
url: 'https://example.com',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('app: Präfix → App öffnen', () => {
|
||||||
|
expect(resolveCommand('app:Spotify')).toEqual({
|
||||||
|
type: 'app',
|
||||||
|
name: 'Spotify',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('save: Präfix → Datei auf Desktop speichern', () => {
|
||||||
|
expect(resolveCommand('save:{"filename":"test.txt","content":"hallo"}')).toEqual({
|
||||||
|
type: 'save',
|
||||||
|
filename: 'test.txt',
|
||||||
|
content: 'hallo',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('unbekannter Befehl → unknown', () => {
|
||||||
|
expect(resolveCommand('gibts_nicht')).toEqual({ type: 'unknown' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('volume_up ist bekannter Shortcut', () => {
|
||||||
|
const result = resolveCommand('volume_up');
|
||||||
|
expect(result.type).toBe('applescript');
|
||||||
|
expect(result.script).toContain('output volume');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
const { exec, execSync } = require('child_process');
|
||||||
|
const util = require('util');
|
||||||
|
const fs = require('fs');
|
||||||
|
const execAsync = util.promisify(exec);
|
||||||
|
|
||||||
|
const SCRIPTS = {
|
||||||
|
spotify_play: 'tell application "Spotify" to play',
|
||||||
|
spotify_pause: 'tell application "Spotify" to pause',
|
||||||
|
spotify_next: 'tell application "Spotify" to next track',
|
||||||
|
spotify_prev: 'tell application "Spotify" to previous track',
|
||||||
|
music_play: 'tell application "Music" to play',
|
||||||
|
music_pause: 'tell application "Music" to pause',
|
||||||
|
music_next: 'tell application "Music" to next track',
|
||||||
|
mail_open: 'tell application "Mail" to activate',
|
||||||
|
mail_unread: 'tell application "Mail" to return (count of (messages of inbox whose read status is false))',
|
||||||
|
calendar_open: 'tell application "Calendar" to activate',
|
||||||
|
notes_open: 'tell application "Notes" to activate',
|
||||||
|
volume_up: 'set volume output volume (output volume of (get volume settings) + 10)',
|
||||||
|
volume_down: 'set volume output volume (output volume of (get volume settings) - 10)',
|
||||||
|
volume_mute: 'set volume output muted true',
|
||||||
|
volume_unmute: 'set volume output muted false',
|
||||||
|
dark_mode_on: 'tell app "System Events" to tell appearance preferences to set dark mode to true',
|
||||||
|
dark_mode_off: 'tell app "System Events" to tell appearance preferences to set dark mode to false',
|
||||||
|
screenshot: 'do shell script "screencapture -x ~/Desktop/fox-screenshot-$(date +%Y%m%d-%H%M%S).png"',
|
||||||
|
};
|
||||||
|
|
||||||
|
function resolveCommand(command) {
|
||||||
|
if (SCRIPTS[command]) {
|
||||||
|
return { type: 'applescript', script: SCRIPTS[command] };
|
||||||
|
}
|
||||||
|
if (command.startsWith('script:')) {
|
||||||
|
return { type: 'applescript', script: command.slice(7) };
|
||||||
|
}
|
||||||
|
if (command.startsWith('open:')) {
|
||||||
|
return { type: 'open', url: command.slice(5) };
|
||||||
|
}
|
||||||
|
if (command.startsWith('app:')) {
|
||||||
|
return { type: 'app', name: command.slice(4) };
|
||||||
|
}
|
||||||
|
if (command.startsWith('save:')) {
|
||||||
|
return { type: 'save', ...JSON.parse(command.slice(5)) };
|
||||||
|
}
|
||||||
|
return { type: 'unknown' };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function executeMacCommand(command) {
|
||||||
|
try {
|
||||||
|
const resolved = resolveCommand(command);
|
||||||
|
|
||||||
|
if (resolved.type === 'applescript') {
|
||||||
|
const { stdout } = await execAsync(`osascript -e '${resolved.script}'`);
|
||||||
|
return { success: true, output: stdout.trim() };
|
||||||
|
}
|
||||||
|
if (resolved.type === 'open') {
|
||||||
|
execSync(`open "${resolved.url}"`);
|
||||||
|
return { success: true, output: 'Geöffnet' };
|
||||||
|
}
|
||||||
|
if (resolved.type === 'app') {
|
||||||
|
execSync(`open -a "${resolved.name}"`);
|
||||||
|
return { success: true, output: `${resolved.name} geöffnet` };
|
||||||
|
}
|
||||||
|
if (resolved.type === 'save') {
|
||||||
|
const filePath = `${process.env.HOME}/Desktop/${resolved.filename}`;
|
||||||
|
fs.writeFileSync(filePath, resolved.content, 'utf8');
|
||||||
|
return { success: true, output: `Gespeichert: ${filePath}` };
|
||||||
|
}
|
||||||
|
return { success: false, output: 'Unbekannter Befehl' };
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
return { success: false, output: err.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { executeMacCommand, resolveCommand, SCRIPTS };
|
||||||
Loading…
Reference in New Issue