hishtory/shared/data.go
2022-01-09 16:39:13 -08:00

91 lines
2.3 KiB
Go

package shared
import (
"fmt"
"os"
"path"
"strings"
"time"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type HistoryEntry struct {
UserSecret string `json:"user_secret" gorm:"index"`
LocalUsername string `json:"local_username"`
Hostname string `json:"hostname"`
Command string `json:"command"`
CurrentWorkingDirectory string `json:"current_working_directory"`
ExitCode int `json:"exit_code"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
}
const (
DB_PATH = ".hishtory.db"
)
func Persist(entry HistoryEntry) error {
db, err := OpenDB()
if err != nil {
return err
}
conn, err := db.DB()
defer conn.Close()
db.Create(&entry).Commit()
return nil
}
func OpenDB() (*gorm.DB, error) {
homedir, err := os.UserHomeDir()
if err != nil {
return nil, fmt.Errorf("failed to get user's home directory: %v", err)
}
db, err := gorm.Open(sqlite.Open(path.Join(homedir, DB_PATH)), &gorm.Config{})
if err != nil {
return nil, fmt.Errorf("failed to connect to the DB: %v", err)
}
db.AutoMigrate(&HistoryEntry{})
return db, nil
}
func Search(db *gorm.DB, userSecret, query string, limit int) ([]*HistoryEntry, error) {
tokens, err := tokenize(query)
if err != nil {
return nil, fmt.Errorf("failed to tokenize query: %v", err)
}
tx := db.Where("user_secret = ?", userSecret)
for _, token := range tokens {
if strings.Contains(token, ":") {
splitToken := strings.SplitN(token, ":", 2)
field := splitToken[0]
val := splitToken[1]
// tx = tx.Where()
panic("TODO(ddworken): Use " + field + val)
} else if strings.HasPrefix(token, "-") {
panic("TODO(ddworken): Implement -foo as filtering out foo")
} else {
wildcardedToken := "%" + token + "%"
tx = tx.Where("(command LIKE ? OR hostname LIKE ? OR current_working_directory LIKE ?)", wildcardedToken, wildcardedToken, wildcardedToken)
}
}
tx = tx.Order("end_time DESC")
if limit > 0 {
tx = tx.Limit(limit)
}
var historyEntries []*HistoryEntry
result := tx.Find(&historyEntries)
if result.Error != nil {
return nil, fmt.Errorf("DB query error: %v", result.Error)
}
return historyEntries, nil
}
func tokenize(query string) ([]string, error) {
if query == "" {
return []string{}, nil
}
return strings.Split(query, " "), nil
}